PageRenderTime 36ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

/Joobsbox/Controllers/AdminController.php

http://github.com/valentinbora/joobsbox-php
PHP | 467 lines | 308 code | 69 blank | 90 comment | 51 complexity | d57c55f2178e5fe3b4485a7f9973f35a MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Admin Controller
  4. *
  5. * Manages the admin panel
  6. *
  7. * @category Joobsbox
  8. * @package Joobsbox_Controller
  9. * @author Valentin Bora <contact@valentinbora.com>
  10. * @license New BSD License http://www.joobsbox.com/joobsbox-php-license
  11. * @version 1.0
  12. * @link http://docs.joobsbox.com/php
  13. */
  14. /**
  15. * Manages the admin panel
  16. *
  17. * @category Joobsbox
  18. * @package Joobsbox_Controller
  19. * @author Valentin Bora <contact@valentinbora.com>
  20. * @license New BSD License http://www.joobsbox.com/joobsbox-php-license
  21. * @link http://docs.joobsbox.com/php
  22. */
  23. class AdminController extends Zend_Controller_Action
  24. {
  25. private $_alerts = array();
  26. private $_notices = array();
  27. private $_corePlugins = array();
  28. private $_corePluginPath;
  29. private $_pluginPath;
  30. private $_pluginUrl;
  31. private $_corePluginUrl;
  32. private $plugins = array();
  33. private $menuPlugins = array();
  34. private $dashboardCandidates = array();
  35. /**
  36. * Function to sort plugins in the admin menu by usort
  37. *
  38. * @param string $x name of first plugin
  39. * @param string $y name of second plugin
  40. *
  41. * @return int -1 or 1 to reflect order for usort
  42. */
  43. private function _sortFunction($x, $y)
  44. {
  45. if (in_array($x, $this->_corePlugins) && in_array($y, $this->_corePlugins)) {
  46. if (array_search($x, $this->_corePlugins) < array_search($y, $this->_corePlugins)) {
  47. return -1;
  48. } else {
  49. return 1;
  50. }
  51. } else {
  52. if (in_array($x, $this->_corePlugins)) {
  53. return -1;
  54. } else {
  55. return 1;
  56. }
  57. }
  58. }
  59. /**
  60. * Initialization method. Sets up the admin environment
  61. *
  62. * @todo this method is too complex. Split up into multiple smaller methods
  63. * @return void
  64. */
  65. public function init()
  66. {
  67. $url = $_SERVER['REQUEST_URI'];
  68. if (substr($url, -1) != '/') {
  69. header("Location: " . $url . '/');
  70. exit();
  71. }
  72. $this->_configurePluginPaths();
  73. $this->_configureVersion();
  74. $this->_helper->event("admin_panel_init");
  75. $this->_conf = Zend_Registry::get("conf");
  76. $this->_configureTheme();
  77. // Get plugin order from configuration file
  78. if (isset($this->_conf->admin->menu) && !empty($this->_conf->admin->menu)) {
  79. $this->_corePlugins = explode(",", $this->_conf->admin->menu);
  80. }
  81. $translate = Zend_Registry::get("Zend_Translate");
  82. $locale = Zend_Registry::get("Zend_Locale");
  83. // Dig the core plugins
  84. $this->_searchCorePlugins();
  85. // Search for the other plugins - dashboard purposes
  86. $this->_searchAppPlugins();
  87. $this->_storeSidebarConfiguration();
  88. // Arrange sidebar items
  89. uksort($this->menuPlugins, array($this, "_sortFunction"));
  90. // Set up view
  91. $this->view->corePlugins = $this->_corePlugins;
  92. $this->view->corePluginPath = $this->_corePluginPath;
  93. $this->view->pluginPath = $this->_pluginPath;
  94. $this->view->plugins = $this->menuPlugins;
  95. $this->view->pluginsThemePath = str_replace("index.php", "", $this->view->baseUrl);
  96. $this->view->locale = Zend_Registry::get("Zend_Locale");
  97. // Check for different alerts to show
  98. $this->_checkAlerts();
  99. // Load CSS and JS assets
  100. $this->_loadPresentation();
  101. }
  102. private function _configurePluginPaths()
  103. {
  104. $this->_corePluginPath = APPLICATION_DIRECTORY . "/Joobsbox/Plugin";
  105. $this->_corePluginUrl = $this->view->noScriptBaseUrl . "/Joobsbox/Plugin";
  106. $this->_pluginPath = APPLICATION_DIRECTORY . "/plugins";
  107. $this->_pluginUrl = $this->view->noScriptBaseUrl . "/plugins";
  108. }
  109. private function _configureVersion()
  110. {
  111. if (file_exists(APPLICATION_DIRECTORY . "/Joobsbox/Version")) {
  112. $this->view->version = file_get_contents(APPLICATION_DIRECTORY . "/Joobsbox/Version");
  113. } else {
  114. $this->view->version = "0.9.20090701";
  115. @file_put_contents(APPLICATION_DIRECTORY . "/Joobsbox/Version", "0.9.20090701");
  116. }
  117. }
  118. private function _configureTheme()
  119. {
  120. configureTheme("_admin/" . $this->_conf->general->admin_theme, 'index', '/themes/_admin/' . $this->_conf->general->admin_theme . '/layouts');
  121. }
  122. private function _searchCorePlugins()
  123. {
  124. $locale = $this->_conf->general->locale;
  125. foreach (new DirectoryIterator($this->_corePluginPath) as $plugin) {
  126. $name = $plugin->getFilename();
  127. if ($plugin->isDir() && $name[0] != '.' && $name[0] != '_') {
  128. include_once $this->_corePluginPath . "/$name/$name.php";
  129. // Analyze prerequisites
  130. $class = new ReflectionClass(ucfirst($name));
  131. if (file_exists($this->_corePluginPath . '/' . $name . '/config.xml')) {
  132. $this->plugins[$name] = new Zend_Config_Xml($this->_corePluginPath . '/' . $name . '/config.xml', null, array("allowModifications" => true));
  133. $this->plugins[$name]->paths = array();
  134. $this->plugins[$name]->paths->dirPath = $this->_corePluginPath;
  135. $this->plugins[$name]->paths->urlPath = $this->_corePluginUrl;
  136. $this->menuPlugins[$name] = $this->plugins[$name];
  137. $this->_pluginPaths[$name] = $this->_corePluginPath . '/' . $name;
  138. if (file_exists($this->_pluginPaths[$name] . '/languages/' . $locale . '.mo') && substr((string)$locale, 0, 2) != 'en') {
  139. $translate->addTranslation($this->_pluginPaths[$name] . '/languages/' . $locale . '.mo', $locale);
  140. }
  141. }
  142. if ($class->hasMethod('dashboard')) {
  143. $this->dashboardCandidates[$name] = 1;
  144. }
  145. }
  146. }
  147. }
  148. private function _searchAppPlugins()
  149. {
  150. foreach (new DirectoryIterator($this->_pluginPath) as $plugin) {
  151. $name = $plugin->getFilename();
  152. if ($plugin->isDir() && $name[0] != '.' && $name[0] != '_') {
  153. include_once $this->_pluginPath . "/$name/$name.php";
  154. // Analyze prerequisites
  155. $class = new ReflectionClass(ucfirst($name));
  156. if (file_exists($this->_pluginPath . '/' . $name . '/config.xml')) {
  157. $this->plugins[$name] = new Zend_Config_Xml($this->_pluginPath . '/' . $name . '/config.xml', null, array("allowModifications" => true));
  158. $this->plugins[$name]->paths = array();
  159. $this->plugins[$name]->paths->dirPath = $this->_pluginPath;
  160. $this->plugins[$name]->paths->urlPath = $this->_pluginUrl;
  161. $this->_pluginPaths[$name] = $this->_pluginPath . '/' . $name;
  162. }
  163. if ($class->hasMethod('dashboard')) {
  164. $this->dashboardCandidates[$name] = 1;
  165. }
  166. }
  167. }
  168. }
  169. private function _checkAlerts()
  170. {
  171. $session = new Zend_Session_Namespace("AdminPanel");
  172. $this->_alerts = array_merge($this->_alerts, $this->_helper->FlashMessenger->getMessages());
  173. if (isset($session->alerts)) {
  174. $this->_alerts = array_merge($this->_alerts, array_unique($session->alerts));
  175. unset($session->alerts);
  176. }
  177. }
  178. private function _loadPresentation()
  179. {
  180. $this->view->css->load("reset.css", "global.css", "admin.css");
  181. $this->view->headScript()->prependScript($this->view->translateHash . 'var baseUrl = "' . $this->view->baseUrl . '";' . ' var href = "' . $_SERVER['REQUEST_URI'] . '";', 'text/javascript', array('charset' => 'UTF-8'));
  182. $this->view->js->load('functions.js');
  183. $this->view->asset->load("jquery", "jquery-pngfix");
  184. $this->view->js->load(array('global.js', 100));
  185. }
  186. private function _storeSidebarConfiguration()
  187. {
  188. $menuPlugins = array_keys($this->menuPlugins);
  189. if(count(array_diff(explode(",", $this->_conf->admin->menu), $menuPlugins))) {
  190. // Write it to config so that we don't miss it furtherwise
  191. $tmp = new Zend_Config_Xml("config/config.xml", null, array('allowModifications' => true));
  192. $tmp->admin->menu = implode(",", $menuPlugins);
  193. $writer = new Zend_Config_Writer_Xml(array('config' => $tmp, 'filename' => 'config/config.xml'));
  194. $writer->write();
  195. unset($tmp, $writer);
  196. }
  197. }
  198. /**
  199. * Used to save sorted menu from the client side
  200. *
  201. * @return void
  202. */
  203. public function sortmenuAction()
  204. {
  205. $conf = new Zend_Config_Xml("config/config.xml", null, array(
  206. 'skipExtends' => true,
  207. 'allowModifications' => true)
  208. );
  209. $order = implode(",", $_POST['item']);
  210. $conf->admin->menu = $order;
  211. // Write the configuration file
  212. $writer = new Zend_Config_Writer_Xml(array(
  213. 'config' => $conf,
  214. 'filename' => 'config/config.xml')
  215. );
  216. $writer->write();
  217. exit(0);
  218. }
  219. /**
  220. * Handles admin homepage
  221. *
  222. * @return void
  223. */
  224. public function indexAction()
  225. {
  226. if (!$this->verifyAccess()) {
  227. $sess = new Zend_Session_Namespace("auth");
  228. $sess->loginSuccessRedirectUrl = $_SERVER['REQUEST_URI'];
  229. $this->_redirect("user/login");
  230. }
  231. $this->_prepareDashboard();
  232. $this->view->currentPluginName = "dashboard";
  233. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  234. $viewRenderer->setNoController(false);
  235. $viewRenderer->setNoRender(false);
  236. $this->view->alerts = $this->_alerts;
  237. $this->view->notices = $this->_notices;
  238. }
  239. /**
  240. * Used to prepare and render dashboard plugins
  241. *
  242. * @return void
  243. */
  244. private function _prepareDashboard()
  245. {
  246. $dashboardPlugins = explode(",", $this->_conf->admin->dashboard);
  247. $this->view->dashboard = array();
  248. foreach ($dashboardPlugins as $pluginName) {
  249. $pluginName = trim($pluginName);
  250. if (isset($this->dashboardCandidates[$pluginName])) {
  251. $plugin = $this->_loadPlugin($pluginName, false);
  252. if (method_exists($plugin, "dashboard")) {
  253. $plugin->dashboard();
  254. }
  255. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  256. $this->view->dashboard[$pluginName] = array(
  257. "options" => $this->plugins[ucfirst($pluginName)],
  258. "content" => $viewRenderer->view->render('dashboard.phtml')
  259. );
  260. }
  261. }
  262. // Make some checks
  263. try {
  264. $search = new Joobsbox_Model_Search;
  265. if (!$search->enabled) {
  266. // Oopsie
  267. $this->_alerts[] = $this->view->translate("Search doesn't work because Joobsbox/SearchIndexes doesn't have write permissions. Please allow the server to write to that folder!");
  268. }
  269. } catch(Exception $e) {
  270. }
  271. // Coming from elsewhere
  272. $session = new Zend_Session_Namespace('AdminPanel');
  273. if (isset($session->notices)) {
  274. $this->_notices = array_merge($this->_notices, $session->notices);
  275. unset($session->notices);
  276. }
  277. }
  278. /**
  279. * Used to route plugin calls to their specific pages
  280. *
  281. * @return void
  282. */
  283. private function _router()
  284. {
  285. if (!$this->verifyAccess()) {
  286. $this->_redirect("user/login");
  287. }
  288. $action = $this->getRequest()->getParam('action');
  289. $pluginNames = array_keys($this->plugins);
  290. if (($pluginIndex = array_search($action, array_map('strtolower', array_keys($this->plugins)))) !== false) {
  291. $this->_loadPlugin($pluginNames[$pluginIndex]);
  292. }
  293. $this->view->alerts = $this->_alerts;
  294. $this->view->notices = $this->_notices;
  295. }
  296. /**
  297. * Used to load a plugin with a specific name and inject its various dependencies
  298. *
  299. * @param string $pluginName plugin name to load
  300. * @param boolean $return if $return is true, it won't render the plugin
  301. *
  302. * @return mixed the requested plugin object
  303. */
  304. private function _loadPlugin($pluginName, $return = true)
  305. {
  306. $view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;
  307. $view->js->addPath('/plugins/' . $pluginName . '/js');
  308. $view->js->addPath('/plugins/' . $pluginName);
  309. $view->css->addPath('/plugins/' . $pluginName . '/css');
  310. $view->css->addPath('/plugins/' . $pluginName);
  311. $view->js->addPath('/Joobsbox/Plugin/' . $pluginName . '/js');
  312. $view->js->addPath('/Joobsbox/Plugin/' . $pluginName);
  313. $view->css->addPath('/Joobsbox/Plugin/' . $pluginName . '/css');
  314. $view->css->addPath('/Joobsbox/Plugin/' . $pluginName);
  315. $pluginUrl = $_SERVER['REQUEST_URI'];
  316. if ($pluginUrl[strlen($pluginUrl)-1] != '/') {
  317. $pluginUrl .= '/';
  318. }
  319. $view->pluginUrl = $pluginUrl;
  320. $view->js->write('var pluginUrl="' . $pluginUrl . '";');
  321. include_once $this->_pluginPaths[$pluginName] . '/' . $pluginName . '.php';
  322. $plugin = new $pluginName;
  323. $plugin->setPluginName($pluginName);
  324. $view->currentPluginName = $pluginName;
  325. $plugin->view = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer')->view;;
  326. $plugin->path = $plugin->view->path = $this->plugins[$pluginName]->paths->urlPath . '/' . $pluginName;
  327. $plugin->dirPath = $this->plugins[$pluginName]->paths->dirPath . '/' . $pluginName;
  328. $plugin->view->dirPath = $this->_pluginPaths[$pluginName] . '/';
  329. $plugin->_helper = $this->_helper;
  330. $plugin->alerts = $this->_alerts;
  331. $plugin->notices = $this->_notices;
  332. $plugin->corePlugins = $this->_corePlugins;
  333. $plugin->request = $this->getRequest();
  334. $plugin->ajax = false;
  335. $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
  336. $viewRenderer->view->addScriptPath($this->_pluginPath . '/' . $pluginName . '/views');
  337. $viewRenderer->view->addScriptPath($this->_corePluginPath . '/' . $pluginName . '/views');
  338. $viewRenderer->setNoController(true);
  339. $viewRenderer->setViewScriptPathNoControllerSpec(':action.:suffix');
  340. if (method_exists($plugin, "init")) {
  341. $plugin->init();
  342. }
  343. $translate = Zend_Registry::get("Zend_Translate");
  344. $locale = Zend_Registry::get("Zend_Locale");
  345. if (file_exists($plugin->dirPath . '/languages/' . $locale . '.mo') && substr((string)$locale, 0, 2) != 'en') {
  346. $translate->addTranslation($plugin->dirPath . '/languages/' . $locale . '.mo', $locale);
  347. }
  348. if ($return) {
  349. Zend_Registry::get("TranslationHelper")->regenerateHash();
  350. $controllerAction = $this->getRequest()->getParam('action');
  351. $action = substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], $controllerAction)+strlen($controllerAction)+1);
  352. if ($pos = strpos($action, '/') !== false) {
  353. $action = substr($action, 0, strpos($action, '/'));
  354. }
  355. $fullAction = $action . "Action";
  356. if (method_exists($plugin, $fullAction)) {
  357. call_user_func(array($plugin, $fullAction));
  358. $this->render($action);
  359. } elseif (method_exists($plugin, "indexAction")) {
  360. call_user_func(array($plugin, "indexAction"));
  361. }
  362. }
  363. Zend_Registry::set("Translation_Hash", $translate->getMessages());
  364. Zend_Registry::get("TranslationHelper")->regenerateHash();
  365. $tit = "title_" . Zend_Registry::get("Zend_Locale");
  366. $this->view->headTitle()->prepend($this->plugins[$pluginName]->main->$tit);
  367. if (!$return) {
  368. $viewRenderer->setNoRender();
  369. }
  370. if ($plugin->ajax) {
  371. echo $viewRenderer->view->render('dashboard.phtml'); die();
  372. }
  373. return $plugin;
  374. }
  375. /**
  376. * Check that the current user is logged in
  377. *
  378. * @return void
  379. */
  380. public function verifyAccess()
  381. {
  382. return Zend_Auth::getInstance()->hasIdentity();
  383. }
  384. /**
  385. * Used to route plugin calls
  386. *
  387. * @param string $methodName method name to be called. This is a magic function
  388. * @param array $params method parameters
  389. *
  390. * @return void
  391. */
  392. public function __call($methodName, $params)
  393. {
  394. if (!method_exists($this, $methodName)) {
  395. $this->_router();
  396. }
  397. }
  398. }