Block.php 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. <?php
  2. namespace Drupal\block\Entity;
  3. use Drupal\Core\Cache\Cache;
  4. use Drupal\Core\Condition\ConditionPluginCollection;
  5. use Drupal\Core\Config\Entity\ConfigEntityBase;
  6. use Drupal\block\BlockPluginCollection;
  7. use Drupal\block\BlockInterface;
  8. use Drupal\Core\Config\Entity\ConfigEntityInterface;
  9. use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
  10. use Drupal\Core\Entity\EntityStorageInterface;
  11. /**
  12. * Defines a Block configuration entity class.
  13. *
  14. * @ConfigEntityType(
  15. * id = "block",
  16. * label = @Translation("Block"),
  17. * handlers = {
  18. * "access" = "Drupal\block\BlockAccessControlHandler",
  19. * "view_builder" = "Drupal\block\BlockViewBuilder",
  20. * "list_builder" = "Drupal\block\BlockListBuilder",
  21. * "form" = {
  22. * "default" = "Drupal\block\BlockForm",
  23. * "delete" = "Drupal\block\Form\BlockDeleteForm"
  24. * }
  25. * },
  26. * admin_permission = "administer blocks",
  27. * entity_keys = {
  28. * "id" = "id",
  29. * "status" = "status"
  30. * },
  31. * links = {
  32. * "delete-form" = "/admin/structure/block/manage/{block}/delete",
  33. * "edit-form" = "/admin/structure/block/manage/{block}",
  34. * "enable" = "/admin/structure/block/manage/{block}/enable",
  35. * "disable" = "/admin/structure/block/manage/{block}/disable",
  36. * },
  37. * config_export = {
  38. * "id",
  39. * "theme",
  40. * "region",
  41. * "weight",
  42. * "provider",
  43. * "plugin",
  44. * "settings",
  45. * "visibility",
  46. * },
  47. * lookup_keys = {
  48. * "theme"
  49. * }
  50. * )
  51. */
  52. class Block extends ConfigEntityBase implements BlockInterface, EntityWithPluginCollectionInterface {
  53. /**
  54. * The ID of the block.
  55. *
  56. * @var string
  57. */
  58. protected $id;
  59. /**
  60. * The plugin instance settings.
  61. *
  62. * @var array
  63. */
  64. protected $settings = [];
  65. /**
  66. * The region this block is placed in.
  67. *
  68. * @var string
  69. */
  70. protected $region;
  71. /**
  72. * The block weight.
  73. *
  74. * @var int
  75. */
  76. protected $weight;
  77. /**
  78. * The plugin instance ID.
  79. *
  80. * @var string
  81. */
  82. protected $plugin;
  83. /**
  84. * The visibility settings for this block.
  85. *
  86. * @var array
  87. */
  88. protected $visibility = [];
  89. /**
  90. * The plugin collection that holds the block plugin for this entity.
  91. *
  92. * @var \Drupal\block\BlockPluginCollection
  93. */
  94. protected $pluginCollection;
  95. /**
  96. * The available contexts for this block and its visibility conditions.
  97. *
  98. * @var array
  99. */
  100. protected $contexts = [];
  101. /**
  102. * The visibility collection.
  103. *
  104. * @var \Drupal\Core\Condition\ConditionPluginCollection
  105. */
  106. protected $visibilityCollection;
  107. /**
  108. * The condition plugin manager.
  109. *
  110. * @var \Drupal\Core\Executable\ExecutableManagerInterface
  111. */
  112. protected $conditionPluginManager;
  113. /**
  114. * The theme that includes the block plugin for this entity.
  115. *
  116. * @var string
  117. */
  118. protected $theme;
  119. /**
  120. * {@inheritdoc}
  121. */
  122. public function getPlugin() {
  123. return $this->getPluginCollection()->get($this->plugin);
  124. }
  125. /**
  126. * Encapsulates the creation of the block's LazyPluginCollection.
  127. *
  128. * @return \Drupal\Component\Plugin\LazyPluginCollection
  129. * The block's plugin collection.
  130. */
  131. protected function getPluginCollection() {
  132. if (!$this->pluginCollection) {
  133. $this->pluginCollection = new BlockPluginCollection(\Drupal::service('plugin.manager.block'), $this->plugin, $this->get('settings'), $this->id());
  134. }
  135. return $this->pluginCollection;
  136. }
  137. /**
  138. * {@inheritdoc}
  139. */
  140. public function getPluginCollections() {
  141. return [
  142. 'settings' => $this->getPluginCollection(),
  143. 'visibility' => $this->getVisibilityConditions(),
  144. ];
  145. }
  146. /**
  147. * {@inheritdoc}
  148. */
  149. public function getPluginId() {
  150. return $this->plugin;
  151. }
  152. /**
  153. * {@inheritdoc}
  154. */
  155. public function getRegion() {
  156. return $this->region;
  157. }
  158. /**
  159. * {@inheritdoc}
  160. */
  161. public function getTheme() {
  162. return $this->theme;
  163. }
  164. /**
  165. * {@inheritdoc}
  166. */
  167. public function getWeight() {
  168. return $this->weight;
  169. }
  170. /**
  171. * {@inheritdoc}
  172. */
  173. public function label() {
  174. $settings = $this->get('settings');
  175. if ($settings['label']) {
  176. return $settings['label'];
  177. }
  178. else {
  179. $definition = $this->getPlugin()->getPluginDefinition();
  180. return $definition['admin_label'];
  181. }
  182. }
  183. /**
  184. * Sorts active blocks by weight; sorts inactive blocks by name.
  185. */
  186. public static function sort(ConfigEntityInterface $a, ConfigEntityInterface $b) {
  187. // Separate enabled from disabled.
  188. $status = (int) $b->status() - (int) $a->status();
  189. if ($status !== 0) {
  190. return $status;
  191. }
  192. // Sort by weight.
  193. $weight = $a->getWeight() - $b->getWeight();
  194. if ($weight) {
  195. return $weight;
  196. }
  197. // Sort by label.
  198. return strcmp($a->label(), $b->label());
  199. }
  200. /**
  201. * {@inheritdoc}
  202. */
  203. public function calculateDependencies() {
  204. parent::calculateDependencies();
  205. $this->addDependency('theme', $this->theme);
  206. return $this;
  207. }
  208. /**
  209. * {@inheritdoc}
  210. */
  211. public function postSave(EntityStorageInterface $storage, $update = TRUE) {
  212. parent::postSave($storage, $update);
  213. // Entity::postSave() calls Entity::invalidateTagsOnSave(), which only
  214. // handles the regular cases. The Block entity has one special case: a
  215. // newly created block may *also* appear on any page in the current theme,
  216. // so we must invalidate the associated block's cache tag (which includes
  217. // the theme cache tag).
  218. if (!$update) {
  219. Cache::invalidateTags($this->getCacheTagsToInvalidate());
  220. }
  221. }
  222. /**
  223. * {@inheritdoc}
  224. */
  225. public function getVisibility() {
  226. return $this->getVisibilityConditions()->getConfiguration();
  227. }
  228. /**
  229. * {@inheritdoc}
  230. */
  231. public function setVisibilityConfig($instance_id, array $configuration) {
  232. $conditions = $this->getVisibilityConditions();
  233. if (!$conditions->has($instance_id)) {
  234. $configuration['id'] = $instance_id;
  235. $conditions->addInstanceId($instance_id, $configuration);
  236. }
  237. else {
  238. $conditions->setInstanceConfiguration($instance_id, $configuration);
  239. }
  240. return $this;
  241. }
  242. /**
  243. * {@inheritdoc}
  244. */
  245. public function getVisibilityConditions() {
  246. if (!isset($this->visibilityCollection)) {
  247. $this->visibilityCollection = new ConditionPluginCollection($this->conditionPluginManager(), $this->get('visibility'));
  248. }
  249. return $this->visibilityCollection;
  250. }
  251. /**
  252. * {@inheritdoc}
  253. */
  254. public function getVisibilityCondition($instance_id) {
  255. return $this->getVisibilityConditions()->get($instance_id);
  256. }
  257. /**
  258. * Gets the condition plugin manager.
  259. *
  260. * @return \Drupal\Core\Executable\ExecutableManagerInterface
  261. * The condition plugin manager.
  262. */
  263. protected function conditionPluginManager() {
  264. if (!isset($this->conditionPluginManager)) {
  265. $this->conditionPluginManager = \Drupal::service('plugin.manager.condition');
  266. }
  267. return $this->conditionPluginManager;
  268. }
  269. /**
  270. * {@inheritdoc}
  271. */
  272. public function setRegion($region) {
  273. $this->region = $region;
  274. return $this;
  275. }
  276. /**
  277. * {@inheritdoc}
  278. */
  279. public function setWeight($weight) {
  280. $this->weight = $weight;
  281. return $this;
  282. }
  283. /**
  284. * {@inheritdoc}
  285. */
  286. public function createDuplicateBlock($new_id = NULL, $new_theme = NULL) {
  287. $duplicate = parent::createDuplicate();
  288. if (!empty($new_id)) {
  289. $duplicate->id = $new_id;
  290. }
  291. if (!empty($new_theme)) {
  292. $duplicate->theme = $new_theme;
  293. }
  294. return $duplicate;
  295. }
  296. /**
  297. * {@inheritdoc}
  298. */
  299. public function preSave(EntityStorageInterface $storage) {
  300. parent::preSave($storage);
  301. // Ensure the region is valid to mirror the behavior of block_rebuild().
  302. // This is done primarily for backwards compatibility support of
  303. // \Drupal\block\BlockInterface::BLOCK_REGION_NONE.
  304. $regions = system_region_list($this->theme);
  305. if (!isset($regions[$this->region]) && $this->status()) {
  306. $this
  307. ->setRegion(system_default_region($this->theme))
  308. ->disable();
  309. }
  310. }
  311. }