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