0009810: Plugins architecture
[tine20] / tine20 / Tinebase / Controller / Abstract.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Tinebase
6  * @subpackage  Controller
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Philipp Schuele <p.schuele@metaways.de>
9  * @copyright   Copyright (c) 2007-2011 Metaways Infosystems GmbH (http://www.metaways.de)
10  * 
11  */
12
13 /**
14  * controller abstract for applications
15  *
16  * @package     Tinebase
17  * @subpackage  Controller
18  */
19 abstract class Tinebase_Controller_Abstract extends Tinebase_Pluggable_Abstract implements Tinebase_Controller_Interface
20 {
21     /**
22      * default settings
23      * 
24      * @var array
25      */
26     protected $_defaultsSettings = array();
27     
28     
29     /**
30      * holds the default Model of this application
31      * @var string
32      */
33     protected static $_defaultModel = NULL;
34     
35     /**
36      * application name (is needed in checkRight())
37      *
38      * @var string
39      */
40     protected $_applicationName = '';
41     
42     /**
43      * disable events on demand
44      * 
45      * @var mixed   false => no events filtered, true => all events filtered, array => disable only specific events
46      */
47     protected $_disabledEvents = false;
48     
49     /**
50      * generic check admin rights function
51      * rules: 
52      * - ADMIN right includes all other rights
53      * - MANAGE_* right includes VIEW_* right 
54      * - results are cached if caching is active (with cache tag 'rights')
55      * 
56      * @param   string  $_right to check
57      * @param   boolean $_throwException [optional]
58      * @param   boolean $_includeTinebaseAdmin [optional]
59      * @return  boolean
60      * @throws  Tinebase_Exception_UnexpectedValue
61      * @throws  Tinebase_Exception_AccessDenied
62      * 
63      * @todo move that to *_Acl_Rights
64      * @todo include Tinebase admin? atm only the application admin right is checked
65      * @todo think about moving the caching to Tinebase_Acl_Roles and use only a class cache as it is difficult (and slow?) to invalidate
66      */
67     public function checkRight($_right, $_throwException = TRUE, $_includeTinebaseAdmin = TRUE) 
68     {
69         if (empty($this->_applicationName)) {
70             throw new Tinebase_Exception_UnexpectedValue('No application name defined!');
71         }
72         
73         $right = strtoupper($_right);
74         
75         $cache = Tinebase_Core::getCache();
76         $cacheId = convertCacheId('checkRight' . Tinebase_Core::getUser()->getId() . $right . $this->_applicationName);
77         $result = $cache->load($cacheId);
78         
79         if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' . $cacheId);
80         
81         if (!$result) {
82             $applicationRightsClass = $this->_applicationName . '_Acl_Rights';
83             
84             // array with the rights that should be checked, ADMIN is in it per default
85             $rightsToCheck = ($_includeTinebaseAdmin) ? array(Tinebase_Acl_Rights::ADMIN) : array();
86             
87             if (preg_match("/VIEW_([A-Z_]*)/", $right, $matches)) {
88                 // manage right includes view right
89                 $rightsToCheck[] = constant($applicationRightsClass. '::MANAGE_' . $matches[1]);
90             } 
91             
92             $rightsToCheck[] = constant($applicationRightsClass. '::' . $right);
93             
94             $result = FALSE;
95             
96             if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__
97                 . ' Checking rights: ' . print_r($rightsToCheck, TRUE));
98             
99             foreach ($rightsToCheck as $rightToCheck) {
100                 if (Tinebase_Acl_Roles::getInstance()->hasRight($this->_applicationName, Tinebase_Core::getUser()->getId(), $rightToCheck)) {
101                     $result = TRUE;
102                     break;
103                 }
104             }
105             
106             $cache->save($result, $cacheId, array('rights'), 120);
107         }
108         
109         if (!$result && $_throwException) {
110             throw new Tinebase_Exception_AccessDenied("You are not allowed to $right in application $this->_applicationName !");
111         }
112         
113         return $result;
114     }
115     
116     /**
117      * Returns default settings for app
118      *
119      * @param boolean $_resolve if some values should be resolved
120      * @return  array settings data
121      */
122     public function getConfigSettings($_resolve = FALSE)
123     {
124         $appConfig = Tinebase_Config::getAppConfig($this->_applicationName);
125         if ($appConfig != NULL) {
126             $settings = $appConfig::getInstance()->get(
127                 Tinebase_Config::APPDEFAULTS, 
128                 new Tinebase_Config_Struct($this->_defaultsSettings)
129             )->toArray();
130         } else { 
131             $settings = $this->_defaultsSettings;
132         }
133         return ($_resolve) ? $this->_resolveConfigSettings($settings) : $settings;
134     }
135     
136     /**
137      * resolve some settings
138      * 
139      * @param array $_settings
140      */
141     protected function _resolveConfigSettings($_settings)
142     {
143         return $_settings;
144     }
145     
146     /**
147      * save settings
148      * 
149      * @param array $_settings
150      * @return void
151      */
152     public function saveConfigSettings($_settings)
153     {
154         // only admins are allowed to do this
155         $this->checkRight(Tinebase_Acl_Rights::ADMIN);
156         
157         $appConfig = Tinebase_Config::getAppConfig($this->_applicationName);
158         
159         if ($appConfig !== NULL) {
160             $appConfig::getInstance()->set(Tinebase_Config::APPDEFAULTS, $_settings);
161         }
162     }
163     
164     /**
165      * returns the default model of this application
166      * @return string
167      */
168     public static function getDefaultModel()
169     {
170         return static::$_defaultModel;
171     }
172     
173     /**
174      * returns controller instance for given $_controllerName
175      * 
176      * @param string $_controllerName
177      * @return Tinebase_Controller
178      */
179     public static function getController($_controllerName)
180     {
181         if (! class_exists($_controllerName)) {
182             throw new Exception("Controller" . $_controllerName . "not found.");
183         }
184         
185         if (!in_array('Tinebase_Controller_Interface', class_implements($_controllerName))) {
186             throw new Exception("Controller $_controllerName does not implement Tinebase_Controller_Interface.");
187         }
188         
189         return call_user_func(array($_controllerName, 'getInstance'));
190     }
191 }