Merge pull request #1765 from lynndanzig/master
[civicrm-core.git] / CRM / Core / Component.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.4 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 * Component stores all the static and dynamic information of the various
30 * CiviCRM components
31 *
32 * @package CRM
33 * @copyright CiviCRM LLC (c) 2004-2013
34 * $Id$
35 *
36 */
37 class CRM_Core_Component {
38
39 /*
40 * End part (filename) of the component information class'es name
41 * that needs to be present in components main directory.
42 */
43 CONST COMPONENT_INFO_CLASS = 'Info';
44
45 private static $_info = NULL;
46
47 static $_contactSubTypes = NULL;
48
49 private static function &_info($force = FALSE) {
50 if (self::$_info == NULL || $force) {
51 self::$_info = array();
52 $c = array();
53
54 $config = CRM_Core_Config::singleton();
55 $c = self::getComponents();
56
57 foreach ($c as $name => $comp) {
58 if (in_array($name, $config->enableComponents)) {
59 self::$_info[$name] = $comp;
60 }
61 }
62 }
63
64 return self::$_info;
65 }
66
67 static function get($name, $attribute = NULL) {
68 $comp = CRM_Utils_Array::value($name, self::_info());
69 if ($attribute) {
70 return CRM_Utils_Array::value($attribute, $comp->info);
71 }
72 return $comp;
73 }
74
75 public static function &getComponents($force = FALSE) {
76 static $_cache = NULL;
77
78 if (!$_cache || $force) {
79 $_cache = array();
80
81 $cr = new CRM_Core_DAO_Component();
82 $cr->find(FALSE);
83 while ($cr->fetch()) {
84 $infoClass = $cr->namespace . '_' . self::COMPONENT_INFO_CLASS;
85 require_once (str_replace('_', DIRECTORY_SEPARATOR, $infoClass) . '.php');
86 $infoObject = new $infoClass($cr->name, $cr->namespace, $cr->id);
87 if ($infoObject->info['name'] !== $cr->name) {
88 CRM_Core_Error::fatal("There is a discrepancy between name in component registry and in info file ({$cr->name}).");
89 }
90 $_cache[$cr->name] = $infoObject;
91 unset($infoObject);
92 }
93 }
94
95 return $_cache;
96 }
97
98 static public function &getEnabledComponents($force = FALSE) {
99 return self::_info($force);
100 }
101
102 static public function flushEnabledComponents() {
103 self::getEnabledComponents(TRUE);
104 }
105
106 public static function &getNames($translated = FALSE) {
107 $allComponents = self::getComponents();
108
109 $names = array();
110 foreach ($allComponents as $name => $comp) {
111 if ($translated) {
112 $names[$comp->componentID] = $comp->info['translatedName'];
113 }
114 else {
115 $names[$comp->componentID] = $name;
116 }
117 }
118 return $names;
119 }
120
121 static function invoke(&$args, $type) {
122 $info = self::_info();
123 $config = CRM_Core_Config::singleton();
124
125 $firstArg = CRM_Utils_Array::value(1, $args, '');
126 $secondArg = CRM_Utils_Array::value(2, $args, '');
127 foreach ($info as $name => $comp) {
128 if (in_array($name, $config->enableComponents) &&
129 (($comp->info['url'] === $firstArg && $type == 'main') ||
130 ($comp->info['url'] === $secondArg && $type == 'admin')
131 )
132 ) {
133 if ($type == 'main') {
134 // also set the smarty variables to the current component
135 $template = CRM_Core_Smarty::singleton();
136 $template->assign('activeComponent', $name);
137 if (CRM_Utils_Array::value('formTpl', $comp->info[$name])) {
138 $template->assign('formTpl', $comp->info[$name]['formTpl']);
139 }
140 if (CRM_Utils_Array::value('css', $comp->info[$name])) {
141 $styleSheets = '<style type="text/css">@import url(' . "{$config->resourceBase}css/{$comp->info[$name]['css']});</style>";
142 CRM_Utils_System::addHTMLHead($styleSheet);
143 }
144 }
145 $inv = $comp->getInvokeObject();
146 $inv->$type($args);
147 return TRUE;
148 }
149 }
150 return FALSE;
151 }
152
153 static function xmlMenu() {
154
155 // lets build the menu for all components
156 $info = self::getComponents(TRUE);
157
158 $files = array();
159 foreach ($info as $name => $comp) {
160 $files = array_merge($files,
161 $comp->menuFiles()
162 );
163 }
164
165 return $files;
166 }
167
168 static function &menu() {
169 $info = self::_info();
170 $items = array();
171 foreach ($info as $name => $comp) {
172 $mnu = $comp->getMenuObject();
173
174 $ret = $mnu->permissioned();
175 $items = array_merge($items, $ret);
176
177 $ret = $mnu->main($task);
178 $items = array_merge($items, $ret);
179 }
180 return $items;
181 }
182
183 static function addConfig(&$config, $oldMode = FALSE) {
184 $info = self::_info();
185
186 foreach ($info as $name => $comp) {
187 $cfg = $comp->getConfigObject();
188 $cfg->add($config, $oldMode);
189 }
190 return;
191 }
192
193 static function getComponentID($componentName) {
194 $info = self::_info();
195
196 return $info[$componentName]->componentID;
197 }
198
199 static function getComponentName($componentID) {
200 $info = self::_info();
201
202 $componentName = NULL;
203 foreach ($info as $compName => $component) {
204 if ($component->componentID == $componentID) {
205 $componentName = $compName;
206 break;
207 }
208 }
209
210 return $componentName;
211 }
212
213 static function &getQueryFields() {
214 $info = self::_info();
215 $fields = array();
216 foreach ($info as $name => $comp) {
217 if ($comp->usesSearch()) {
218 $bqr = $comp->getBAOQueryObject();
219 $flds = $bqr->getFields();
220 $fields = array_merge($fields, $flds);
221 }
222 }
223 return $fields;
224 }
225
226 static function alterQuery(&$query, $fnName) {
227 $info = self::_info();
228
229 foreach ($info as $name => $comp) {
230 if ($comp->usesSearch()) {
231 $bqr = $comp->getBAOQueryObject();
232 $bqr->$fnName($query);
233 }
234 }
235 }
236
237 static function from($fieldName, $mode, $side) {
238 $info = self::_info();
239
240 $from = NULL;
241 foreach ($info as $name => $comp) {
242 if ($comp->usesSearch()) {
243 $bqr = $comp->getBAOQueryObject();
244 $from = $bqr->from($fieldName, $mode, $side);
245 if ($from) {
246 return $from;
247 }
248 }
249 }
250 return $from;
251 }
252
253 static function &defaultReturnProperties($mode,
254 $includeCustomFields = TRUE
255 ) {
256 $info = self::_info();
257
258 $properties = NULL;
259 foreach ($info as $name => $comp) {
260 if ($comp->usesSearch()) {
261 $bqr = $comp->getBAOQueryObject();
262 $properties = $bqr->defaultReturnProperties($mode, $includeCustomFields);
263 if ($properties) {
264 return $properties;
265 }
266 }
267 }
268 return $properties;
269 }
270
271 static function &buildSearchForm(&$form) {
272 $info = self::_info();
273
274 foreach ($info as $name => $comp) {
275 if ($comp->usesSearch()) {
276 $bqr = $comp->getBAOQueryObject();
277 $bqr->buildSearchForm($form);
278 }
279 }
280 }
281
282 static function &addShowHide(&$showHide) {
283 $info = self::_info();
284
285 foreach ($info as $name => $comp) {
286 if ($comp->usesSearch()) {
287 $bqr = $comp->getBAOQueryObject();
288 $bqr->addShowHide($showHide);
289 }
290 }
291 }
292
293 static function searchAction(&$row, $id) {
294 $info = self::_info();
295
296 foreach ($info as $name => $comp) {
297 if ($comp->usesSearch()) {
298 $bqr = $comp->getBAOQueryObject();
299 $bqr->searchAction($row, $id);
300 }
301 }
302 }
303
304 static function &contactSubTypes() {
305 if (self::$_contactSubTypes == NULL) {
306 self::$_contactSubTypes = array();
307 }
308 return self::$_contactSubTypes;
309 }
310
311
312 static function &contactSubTypeProperties($subType, $op) {
313 $properties = self::contactSubTypes();
314 if (array_key_exists($subType, $properties) &&
315 array_key_exists($op, $properties[$subType])
316 ) {
317 return $properties[$subType][$op];
318 }
319 return CRM_Core_DAO::$_nullObject;
320 }
321
322 static function &taskList() {
323 $info = self::_info();
324
325 $tasks = array();
326 foreach ($info as $name => $value) {
327 if (CRM_Utils_Array::value('task', $info[$name])) {
328 $tasks += $info[$name]['task'];
329 }
330 }
331 return $tasks;
332 }
333
334 /**
335 * Function to handle table dependencies of components
336 *
337 * @param array $tables array of tables
338 *
339 * @return null
340 * @access public
341 * @static
342 */
343 static function tableNames(&$tables) {
344 $info = self::_info();
345
346 foreach ($info as $name => $comp) {
347 if ($comp->usesSearch()) {
348 $bqr = $comp->getBAOQueryObject();
349 $bqr->tableNames($tables);
350 }
351 }
352 }
353
354 /**
355 * Function to get components info from info file
356 *
357 */
358 static function getComponentsFromFile($crmFolderDir) {
359 $components = array();
360 //traverse CRM folder and check for Info file
361 if (is_dir($crmFolderDir)) {
362 $dir = opendir($crmFolderDir);
363 while ($subDir = readdir($dir)) {
364 // skip the extensions diretory since it has an Info.php file also
365 if ($subDir == 'Extension') {
366 continue;
367 }
368
369 $infoFile = $crmFolderDir . "/{$subDir}/" . self::COMPONENT_INFO_CLASS . '.php';
370 if (file_exists($infoFile)) {
371 $infoClass = 'CRM_' . $subDir . '_' . self::COMPONENT_INFO_CLASS;
372 require_once (str_replace('_', DIRECTORY_SEPARATOR, $infoClass) . '.php');
373 $infoObject = new $infoClass(NULL, NULL, NULL);
374 $components[$infoObject->info['name']] = $infoObject;
375 unset($infoObject);
376 }
377 }
378 }
379
380 return $components;
381 }
382 }
383