Merge pull request #4892 from colemanw/INFRA-132
[civicrm-core.git] / CRM / Core / Block.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
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 *
30 * @package CRM
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * defines a simple implemenation of a drupal block.
38 * blocks definitions and html are in a smarty template file
39 *
40 */
41class CRM_Core_Block {
42
43 /**
100fef9d 44 * The following blocks are supported
6a488035
TO
45 *
46 * @var int
47 */
7da04cde 48 const
6a488035
TO
49 CREATE_NEW = 1,
50 RECENTLY_VIEWED = 2,
51 DASHBOARD = 3,
52 ADD = 4,
53 LANGSWITCH = 5,
54 EVENT = 6,
55 FULLTEXT_SEARCH = 7;
56
57 /**
100fef9d 58 * Template file names for the above blocks
6a488035
TO
59 */
60 static $_properties = NULL;
61
62 /**
100fef9d 63 * Class constructor
6a488035
TO
64 *
65 */
2aa397bc
TO
66 public function __construct() {
67 }
6a488035
TO
68
69 /**
100fef9d 70 * Initialises the $_properties array
6a488035
TO
71 *
72 * @return void
73 */
00be9182 74 public static function initProperties() {
6a488035
TO
75 if (!defined('BLOCK_CACHE_GLOBAL')) {
76 define('BLOCK_CACHE_GLOBAL', 0x0008);
77 }
78
79 if (!defined('BLOCK_CACHE_PER_PAGE')) {
80 define('BLOCK_CACHE_PER_PAGE', 0x0004);
81 }
82
83 if (!defined('BLOCK_NO_CACHE')) {
84 define('BLOCK_NO_CACHE', -1);
85 }
86
87 if (!(self::$_properties)) {
88 $config = CRM_Core_Config::singleton();
89 self::$_properties = array(
90 // set status item to 0 to disable block by default (at install)
91 self::CREATE_NEW => array(
92 'template' => 'CreateNew.tpl',
93 'info' => ts('CiviCRM Create New Record'),
94 'subject' => ts(''),
95 'active' => TRUE,
96 'cache' => BLOCK_CACHE_GLOBAL,
97 'visibility' => 1,
98 'weight' => -100,
99 'status' => 1,
100 'pages' => "civicrm\ncivicrm/*",
101 'region' => $config->userSystem->getDefaultBlockLocation(),
102 ),
103 self::RECENTLY_VIEWED => array(
104 'template' => 'RecentlyViewed.tpl',
105 'info' => ts('CiviCRM Recent Items'),
106 'subject' => ts('Recent Items'),
107 'active' => TRUE,
108 'cache' => BLOCK_NO_CACHE,
109 'visibility' => 1,
110 'weight' => -99,
111 'status' => 1,
112 'pages' => "civicrm\ncivicrm/*",
113 'region' => $config->userSystem->getDefaultBlockLocation(),
114 ),
115 self::DASHBOARD => array(
116 'template' => 'Dashboard.tpl',
117 'info' => ts('CiviCRM Contact Dashboard'),
118 'subject' => '',
119 'active' => TRUE,
120 'cache' => BLOCK_NO_CACHE,
121 'visibility' => 1,
122 'weight' => -98,
123 'status' => 1,
124 'pages' => "civicrm\ncivicrm/*",
125 'region' => $config->userSystem->getDefaultBlockLocation(),
126 ),
127 self::ADD => array(
128 'template' => 'Add.tpl',
129 'info' => ts('CiviCRM Quick Add'),
130 'subject' => ts('New Individual'),
131 'active' => TRUE,
132 'cache' => BLOCK_NO_CACHE,
133 'visibility' => 1,
134 'weight' => -97,
135 'status' => 1,
136 'pages' => "civicrm\ncivicrm/*",
137 'region' => $config->userSystem->getDefaultBlockLocation(),
138 ),
139 self::LANGSWITCH => array(
140 'template' => 'LangSwitch.tpl',
141 'info' => ts('CiviCRM Language Switcher'),
142 'subject' => '',
143 'templateValues' => array(),
144 'active' => TRUE,
145 'cache' => BLOCK_NO_CACHE,
146 'visibility' => 1,
147 'weight' => -96,
148 'status' => 1,
149 'pages' => "civicrm\ncivicrm/*",
150 'region' => $config->userSystem->getDefaultBlockLocation(),
151 ),
152 self::EVENT => array(
153 'template' => 'Event.tpl',
154 'info' => ts('CiviCRM Upcoming Events'),
155 'subject' => ts('Upcoming Events'),
156 'templateValues' => array(),
157 'active' => TRUE,
158 'cache' => BLOCK_NO_CACHE,
159 'visibility' => 1,
160 'weight' => -95,
161 'status' => 0,
162 'pages' => "civicrm\ncivicrm/*",
163 'region' => $config->userSystem->getDefaultBlockLocation(),
164 ),
165 self::FULLTEXT_SEARCH => array(
166 'template' => 'FullTextSearch.tpl',
167 'info' => ts('CiviCRM Full-text Search'),
168 'subject' => ts('Full-text Search'),
169 'active' => TRUE,
fd0bc470 170 'cache' => BLOCK_NO_CACHE,
6a488035
TO
171 'visibility' => 1,
172 'weight' => -94,
173 'status' => 0,
174 'pages' => "civicrm\ncivicrm/*",
175 'region' => $config->userSystem->getDefaultBlockLocation(),
176 ),
177 );
178
179 ksort(self::$_properties);
180 }
181 }
182
183 /**
100fef9d 184 * Returns the desired property from the $_properties array
6a488035 185 *
6a0b768e
TO
186 * @param int $id
187 * One of the class constants (ADD, SEARCH, etc.).
188 * @param string $property
189 * The desired property.
da6b46f4 190 *
6a488035
TO
191 * @return string the value of the desired property
192 */
00be9182 193 public static function getProperty($id, $property) {
6a488035
TO
194 if (!(self::$_properties)) {
195 self::initProperties();
196 }
197 return isset(self::$_properties[$id][$property]) ? self::$_properties[$id][$property] : NULL;
198 }
199
200 /**
100fef9d 201 * Sets the desired property in the $_properties array
6a488035 202 *
6a0b768e
TO
203 * @param int $id
204 * One of the class constants (ADD, SEARCH, etc.).
205 * @param string $property
206 * The desired property.
207 * @param string $value
208 * The value of the desired property.
6a488035
TO
209 *
210 * @return void
211 */
00be9182 212 public static function setProperty($id, $property, $value) {
6a488035
TO
213 if (!(self::$_properties)) {
214 self::initProperties();
215 }
216 self::$_properties[$id][$property] = $value;
217 }
218
219 /**
100fef9d 220 * Returns the whole $_properties array
6a488035
TO
221 *
222 * @return array the $_properties array
223 */
00be9182 224 public static function properties() {
6a488035
TO
225 if (!(self::$_properties)) {
226 self::initProperties();
227 }
228 return self::$_properties;
229 }
230
231 /**
232 * Creates the info block for drupal
233 *
234 * @return array
6a488035 235 */
00be9182 236 public static function getInfo() {
6a488035
TO
237
238 $block = array();
239 foreach (self::properties() as $id => $value) {
240 if ($value['active']) {
241 if (in_array($id, array(
242 self::ADD, self::CREATE_NEW))) {
243 $hasAccess = TRUE;
244 if (!CRM_Core_Permission::check('add contacts') &&
245 !CRM_Core_Permission::check('edit groups')
246 ) {
247 $hasAccess = FALSE;
248 }
249 //validate across edit/view - CRM-5666
250 if ($hasAccess && ($id == self::ADD)) {
251 $hasAccess = CRM_Core_Permission::giveMeAllACLs();
252 }
253 if (!$hasAccess) {
254 continue;
255 }
256 }
257
258 if ($id == self::EVENT &&
259 (!CRM_Core_Permission::access('CiviEvent', FALSE) ||
260 !CRM_Core_Permission::check('view event info')
261 )
262 ) {
263 continue;
264 }
265
266 $block[$id] = array(
267 'info' => $value['info'],
268 'cache' => $value['cache'],
269 'status' => $value['active'],
270 'region' => $value['region'],
271 'visibility' => $value['visibility'],
272 'pages' => $value['pages'],
273 'status' => $value['status'],
274 'weight' => $value['weight'],
275 );
276 }
277 }
278
279 return $block;
280 }
281
282 /**
100fef9d 283 * Set the post action values for the block.
6a488035
TO
284 *
285 * php is lame and u cannot call functions from static initializers
286 * hence this hack
287 *
100fef9d 288 * @param int $id
dd244018 289 *
6a488035 290 * @return void
6a488035
TO
291 */
292 private static function setTemplateValues($id) {
293 switch ($id) {
294 case self::CREATE_NEW:
295 self::setTemplateShortcutValues();
296 break;
297
298 case self::DASHBOARD:
299 self::setTemplateDashboardValues();
300 break;
301
302 case self::ADD:
303 $defaultLocation = CRM_Core_BAO_LocationType::getDefault();
304 $defaultPrimaryLocationId = $defaultLocation->id;
2aa397bc
TO
305 $values = array(
306 'postURL' => CRM_Utils_System::url('civicrm/contact/add', 'reset=1&ct=Individual'),
6a488035
TO
307 'primaryLocationType' => $defaultPrimaryLocationId,
308 );
309
310 foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) {
311 $values[$greeting . '_id'] = CRM_Contact_BAO_Contact_Utils::defaultGreeting('Individual', $greeting);
312 }
313
314 self::setProperty(self::ADD,
315 'templateValues',
316 $values
317 );
318 break;
319
2aa397bc 320 case self::LANGSWITCH:
bf2ab287 321 // gives the currentPath without trailing empty lcMessages to be completed
322 $values = array('queryString' => CRM_Utils_System::getLinksUrl('lcMessages', TRUE, FALSE, FALSE));
323 self::setProperty(self::LANGSWITCH, 'templateValues', $values);
324 break;
2aa397bc 325
6a488035
TO
326 case self::FULLTEXT_SEARCH:
327 $urlArray = array(
328 'fullTextSearchID' => CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionValue',
329 'CRM_Contact_Form_Search_Custom_FullText', 'value', 'name'
330 ));
331 self::setProperty(self::FULLTEXT_SEARCH, 'templateValues', $urlArray);
332 break;
333
334 case self::RECENTLY_VIEWED:
335 $recent = CRM_Utils_Recent::get();
336 self::setProperty(self::RECENTLY_VIEWED, 'templateValues', array('recentlyViewed' => $recent));
337 break;
338
339 case self::EVENT:
340 self::setTemplateEventValues();
341 break;
342 }
343 }
344
345 /**
100fef9d 346 * Create the list of options to create New objects for the application and format is as a block
6a488035
TO
347 *
348 * @return void
6a488035
TO
349 */
350 private static function setTemplateShortcutValues() {
351 $config = CRM_Core_Config::singleton();
352
353 static $shortCuts = array();
354
355 if (!($shortCuts)) {
356 if (CRM_Core_Permission::check('add contacts')) {
357 if (CRM_Core_Permission::giveMeAllACLs()) {
358 $shortCuts = CRM_Contact_BAO_ContactType::getCreateNewList();
359 }
360 }
361
362 // new activity (select target contact)
363 $shortCuts = array_merge($shortCuts, array(
364 array(
365 'path' => 'civicrm/activity',
366 'query' => 'action=add&reset=1&context=standalone',
367 'ref' => 'new-activity',
368 'title' => ts('Activity'),
369 )));
370
371 $components = CRM_Core_Component::getEnabledComponents();
372
373 if (!empty($config->enableComponents)) {
374 // check if we can process credit card contribs
9be1374d 375 $newCredit = CRM_Core_Config::isEnabledBackOfficeCreditCardPayments();
fd0bc470 376
6a488035
TO
377 foreach ($components as $componentName => $obj) {
378 if (in_array($componentName, $config->enableComponents)) {
0e6e8724 379 $obj->creatNewShortcut($shortCuts, $newCredit);
6a488035
TO
380 }
381 }
382 }
383
384 // new email (select recipients)
385 $shortCuts = array_merge($shortCuts, array(
2aa397bc
TO
386 array(
387 'path' => 'civicrm/activity/email/add',
6a488035
TO
388 'query' => 'atype=3&action=add&reset=1&context=standalone',
389 'ref' => 'new-email',
390 'title' => ts('Email'),
391 )));
392
393 if (CRM_Core_Permission::check('edit groups')) {
394 $shortCuts = array_merge($shortCuts, array(
2aa397bc
TO
395 array(
396 'path' => 'civicrm/group/add',
6a488035
TO
397 'query' => 'reset=1',
398 'ref' => 'new-group',
399 'title' => ts('Group'),
400 )));
401 }
402
403 if (CRM_Core_Permission::check('administer CiviCRM')) {
404 $shortCuts = array_merge($shortCuts, array(
2aa397bc
TO
405 array(
406 'path' => 'civicrm/admin/tag',
6a488035
TO
407 'query' => 'reset=1&action=add',
408 'ref' => 'new-tag',
409 'title' => ts('Tag'),
410 )));
411 }
412
413 if (empty($shortCuts)) {
414 return NULL;
415 }
416 }
417
418 $values = array();
7926b999 419 foreach ($shortCuts as $key => $short) {
420 $values[$key] = self::setShortCutValues($short);
6a488035
TO
421 }
422
423 // call links hook to add user defined links
424 CRM_Utils_Hook::links('create.new.shorcuts',
425 NULL,
426 CRM_Core_DAO::$_nullObject,
427 $values,
a9b15f31 428 CRM_Core_DAO::$_nullObject,
6a488035
TO
429 CRM_Core_DAO::$_nullObject
430 );
e65cf508 431
727b675c 432 foreach ($values as $key => $val) {
e65cf508 433 if (!empty($val['title'])) {
727b675c
AH
434 $values[$key]['name'] = CRM_Utils_Array::value('name', $val, $val['title']);
435 }
436 }
6a488035
TO
437
438 self::setProperty(self::CREATE_NEW, 'templateValues', array('shortCuts' => $values));
439 }
440
a0ee3941
EM
441 /**
442 * @param $short
443 *
444 * @return array
445 */
7926b999 446 private static function setShortcutValues($short) {
447 $value = array();
448 if (isset($short['url'])) {
449 $value['url'] = $short['url'];
450 }
451 elseif (isset($short['path'])) {
452 $value['url'] = CRM_Utils_System::url($short['path'], $short['query'], FALSE);
453 }
454 $value['title'] = $short['title'];
455 $value['ref'] = $short['ref'];
456 if (!empty($short['shortCuts'])) {
457 foreach ($short['shortCuts'] as $shortCut) {
458 $value['shortCuts'][] = self::setShortcutValues($shortCut);
459 }
460 }
461 return $value;
462 }
463
6a488035 464 /**
100fef9d 465 * Create the list of dashboard links
6a488035
TO
466 *
467 * @return void
6a488035
TO
468 */
469 private static function setTemplateDashboardValues() {
470 static $dashboardLinks = array();
471 if (CRM_Core_Permission::check('access Contact Dashboard')) {
472 $dashboardLinks = array(
2aa397bc
TO
473 array(
474 'path' => 'civicrm/user',
6a488035
TO
475 'query' => 'reset=1',
476 'title' => ts('My Contact Dashboard'),
477 ));
478 }
479
480 if (empty($dashboardLinks)) {
481 return NULL;
482 }
483
484 $values = array();
485 foreach ($dashboardLinks as $dash) {
486 $value = array();
487 if (isset($dash['url'])) {
488 $value['url'] = $dash['url'];
489 }
490 else {
491 $value['url'] = CRM_Utils_System::url($dash['path'], $dash['query'], FALSE);
492 }
493 $value['title'] = $dash['title'];
494 $value['key'] = CRM_Utils_Array::value('key', $dash);
495 $values[] = $value;
496 }
497 self::setProperty(self::DASHBOARD, 'templateValues', array('dashboardLinks' => $values));
498 }
499
500 /**
100fef9d 501 * Create the list of mail urls for the application and format is as a block
6a488035
TO
502 *
503 * @return void
6a488035
TO
504 */
505 private static function setTemplateMailValues() {
506 static $shortCuts = NULL;
507
508 if (!($shortCuts)) {
509 $shortCuts = array(
2aa397bc
TO
510 array(
511 'path' => 'civicrm/mailing/send',
6a488035
TO
512 'query' => 'reset=1',
513 'title' => ts('Send Mailing'),
514 ),
515 array(
516 'path' => 'civicrm/mailing/browse',
517 'query' => 'reset=1',
518 'title' => ts('Browse Sent Mailings'),
519 ),
520 );
521 }
522
523 $values = array();
524 foreach ($shortCuts as $short) {
525 $value = array();
526 $value['url'] = CRM_Utils_System::url($short['path'], $short['query']);
527 $value['title'] = $short['title'];
528 $values[] = $value;
529 }
530 self::setProperty(self::MAIL, 'templateValues', array('shortCuts' => $values));
531 }
532
533 /**
100fef9d 534 * Create the list of shortcuts for the application and format is as a block
6a488035
TO
535 *
536 * @return void
6a488035
TO
537 */
538 private static function setTemplateMenuValues() {
539 $config = CRM_Core_Config::singleton();
540
541 $path = 'navigation';
542 $values = CRM_Core_Menu::getNavigation();
543 if ($values) {
544 self::setProperty(self::MENU, 'templateValues', array('menu' => $values));
545 }
546 }
547
548 /**
100fef9d 549 * Create the event blocks for upcoming events
6a488035
TO
550 *
551 * @return void
6a488035
TO
552 */
553 private static function setTemplateEventValues() {
554 $config = CRM_Core_Config::singleton();
555
556 $info = CRM_Event_BAO_Event::getCompleteInfo(date("Ymd"));
557
558 if ($info) {
559 $session = CRM_Core_Session::singleton();
560 // check if registration link should be displayed
561 foreach ($info as $id => $event) {
e2d09ab4
EM
562 //@todo FIXME - validRegistraionRequest takes eventID not contactID as a param
563 // this is called via an obscure patch from Joomla event block rendering (only)
6a488035
TO
564 $info[$id]['onlineRegistration'] = CRM_Event_BAO_Event::validRegistrationRequest($event,
565 $session->get('userID')
566 );
567 }
568
569 self::setProperty(self::EVENT, 'templateValues', array('eventBlock' => $info));
570 }
571 }
572
573 /**
574 * Given an id creates a subject/content array
575 *
6a0b768e
TO
576 * @param int $id
577 * Id of the block.
6a488035
TO
578 *
579 * @return array
6a488035 580 */
00be9182 581 public static function getContent($id) {
6a488035
TO
582 // return if upgrade mode
583 $config = CRM_Core_Config::singleton();
584 if ($config->isUpgradeMode()) {
585 return;
586 }
587
588 if (!self::getProperty($id, 'active')) {
589 return NULL;
590 }
591
592 if ($id == self::EVENT &&
593 CRM_Core_Permission::check('view event info')
594 ) {
595 // is CiviEvent enabled?
596 if (!CRM_Core_Permission::access('CiviEvent', FALSE)) {
597 return NULL;
598 }
599 // do nothing
600 }
550b2acf 601 // require 'access CiviCRM' permissons, except for the language switch block
2aa397bc 602 elseif (!CRM_Core_Permission::check('access CiviCRM') && $id != self::LANGSWITCH) {
6a488035
TO
603 return NULL;
604 }
605 elseif ($id == self::ADD) {
606 $hasAccess = TRUE;
607 if (!CRM_Core_Permission::check('add contacts') &&
608 !CRM_Core_Permission::check('edit groups')
609 ) {
610 $hasAccess = FALSE;
611 }
612 //validate across edit/view - CRM-5666
613 if ($hasAccess) {
614 $hasAccess = CRM_Core_Permission::giveMeAllACLs();
615 }
616 if (!$hasAccess) {
617 return NULL;
618 }
619 }
620
621 self::setTemplateValues($id);
622
623 // Suppress Recent Items block if it's empty - CRM-5188
624 if ($id == self::RECENTLY_VIEWED) {
625 $recent = self::getProperty($id, 'templateValues');
626 if (CRM_Utils_Array::crmIsEmptyArray($recent)) {
627 return NULL;
628 }
629 }
630
631 // Suppress Language switcher if language is inherited from CMS - CRM-9971
632 $config = CRM_Core_Config::singleton();
633 if ($id == self::LANGSWITCH && property_exists($config, "inheritLocale") && $config->inheritLocale) {
634 return NULL;
635 }
636
637 $block = array();
638 $block['name'] = 'block-civicrm';
639 $block['id'] = $block['name'] . '_' . $id;
640 $block['subject'] = self::fetch($id, 'Subject.tpl',
641 array('subject' => self::getProperty($id, 'subject'))
642 );
643 $block['content'] = self::fetch($id, self::getProperty($id, 'template'),
644 self::getProperty($id, 'templateValues')
645 );
646
6a488035
TO
647 return $block;
648 }
649
650 /**
651 * Given an id and a template, fetch the contents
652 *
6a0b768e
TO
653 * @param int $id
654 * Id of the block.
655 * @param string $fileName
656 * Name of the template file.
657 * @param array $properties
658 * Template variables.
6a488035
TO
659 *
660 * @return array
6a488035 661 */
00be9182 662 public static function fetch($id, $fileName, $properties) {
6a488035
TO
663 $template = CRM_Core_Smarty::singleton();
664
665 if ($properties) {
666 $template->assign($properties);
667 }
668
669 return $template->fetch('CRM/Block/' . $fileName);
670 }
671}