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