boxes_box.inc 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. /**
  3. * Abstract base class defining a box. A boxes content plugin provides a
  4. * form of options for configuring content and renders content for display.
  5. *
  6. * @see boxes_simple.
  7. */
  8. abstract class boxes_box {
  9. static $boxes; // Static cache of box objects.
  10. public $delta;
  11. public $title;
  12. public $description;
  13. public $options;
  14. public $plugin_key;
  15. public $new;
  16. public $export_type;
  17. /**
  18. * Load existing box by its unique identifier $delta.
  19. */
  20. public static function load($delta, $reset = FALSE) {
  21. if (!isset(self::$boxes[$delta]) || $reset) {
  22. ctools_include('export');
  23. $box = ctools_export_load_object('box', 'names', array($delta));
  24. if (!empty($box) && $values = array_pop($box)) {
  25. self::$boxes[$delta] = self::factory($values->plugin_key, $values);
  26. self::$boxes[$delta]->new = FALSE;
  27. }
  28. }
  29. return isset(self::$boxes[$delta]) && get_class(self::$boxes[$delta]) != 'stdClass' ? self::$boxes[$delta] : NULL;
  30. }
  31. /**
  32. * Instantiate, populate and return a box object.
  33. *
  34. * @param $plugin_key
  35. *
  36. * @param $values
  37. * An array with at least a plugin_key key identifying the plugin class to
  38. * use for instantiating this box.
  39. */
  40. public static function factory($plugin_key, $values) {
  41. ctools_include('plugins');
  42. if ($class = ctools_plugin_load_class('boxes', 'plugins', $plugin_key, 'handler')) {
  43. // While we actually prefer to get objects, we need to allow for either,
  44. // so we convert it all to arrays.
  45. if (is_object($values)) {
  46. $values = (array) $values;
  47. }
  48. $box = new $class();
  49. $box->plugin_key = $plugin_key;
  50. foreach ($box as $key => $value) {
  51. if (isset($values[$key])) {
  52. $box->$key = $values[$key];
  53. }
  54. }
  55. foreach ($box->options_defaults() as $key => $value) {
  56. if (isset($values[$key])) {
  57. $box->options[$key] = $values[$key];
  58. }
  59. }
  60. return $box;
  61. }
  62. return FALSE;
  63. }
  64. /**
  65. * Create a new box.
  66. */
  67. protected function __construct() {
  68. $this->new = TRUE; // A box is new unless it exists in the DB or in code.
  69. $this->options = $this->options_defaults();
  70. }
  71. /**
  72. * Reset the boxes cache.
  73. *
  74. * Both ctools and boxes current maintain caches, ctools of the config and
  75. * boxes of the loaded box objects. We clear them both.
  76. */
  77. public static function reset() {
  78. ctools_include('export');
  79. ctools_export_load_object_reset('box');
  80. self::$boxes = array();
  81. }
  82. /**
  83. * Save a box.
  84. */
  85. public function save() {
  86. if (empty($this->delta)) {
  87. throw new Exception(t('Cannot save box without a specified delta.'));
  88. }
  89. self::reset();
  90. $existing = boxes_box_load($this->delta);
  91. if ($existing && ($existing->export_type & EXPORT_IN_DATABASE)) {
  92. drupal_write_record('box', $this, array('delta'));
  93. }
  94. else {
  95. drupal_write_record('box', $this);
  96. }
  97. $this->new = FALSE;
  98. self::reset();
  99. module_exists('context') ? context_invalidate_cache() : NULL;
  100. }
  101. /**
  102. * Delete a box.
  103. */
  104. public function delete() {
  105. self::reset();
  106. unset(self::$boxes[$this->delta]);
  107. db_delete('box')
  108. ->condition('delta', $this->delta)
  109. ->execute();
  110. module_exists('context') ? context_invalidate_cache() : NULL;
  111. }
  112. /**
  113. * Declare if the box should use a multistep form for the create form.
  114. *
  115. * This might me necessary for forms that use ajax on the options form.
  116. * Currently Context does not load this block correctly and the ajax in the
  117. * form will not work. Methinks Context UI Editor needs to be upgraded to
  118. * D7 AJAX framework for this to not be required. That said the functionality
  119. * is potentially useful even with proper functioning AJAX.
  120. */
  121. public function use_multistep_create() {
  122. return FALSE;
  123. }
  124. /**
  125. * Returns the block cache settings for this box. Subclasses can override this
  126. * to perform more intricate operations around deciding the cache settings of
  127. * the specific box instance.
  128. */
  129. public function cache_setting() {
  130. return DRUPAL_CACHE_CUSTOM;
  131. }
  132. /**
  133. * Declare default options.
  134. */
  135. abstract public function options_defaults();
  136. /**
  137. * Provide options to configure content.
  138. */
  139. abstract public function options_form(&$form_state);
  140. /**
  141. * Render a block. Must return an array with the keys
  142. * 'delta', 'title', 'subject' (same as title) and 'content'.
  143. *
  144. * title AND subject need to be present to avoid that block module overrides
  145. * title.
  146. */
  147. abstract public function render();
  148. }