file Theme.php

Namespace

Drupal\bootstrap
  1. <?php
  2. namespace Drupal\bootstrap;
  3. use Drupal\bootstrap\Plugin\ProviderManager;
  4. use Drupal\bootstrap\Plugin\SettingManager;
  5. use Drupal\bootstrap\Plugin\UpdateManager;
  6. use Drupal\bootstrap\Utility\Crypt;
  7. use Drupal\bootstrap\Utility\Storage;
  8. use Drupal\bootstrap\Utility\StorageItem;
  9. use Drupal\Core\Extension\Extension;
  10. use Drupal\Core\Extension\ThemeHandlerInterface;
  11. use Drupal\Core\Site\Settings;
  12. use Drupal\Core\Url;
  13. /**
  14. * Defines a theme object.
  15. *
  16. * @ingroup utility
  17. */
  18. class Theme {
  19. /**
  20. * Ignores the following directories during file scans of a theme.
  21. *
  22. * @see \Drupal\bootstrap\Theme::IGNORE_ASSETS
  23. * @see \Drupal\bootstrap\Theme::IGNORE_CORE
  24. * @see \Drupal\bootstrap\Theme::IGNORE_DOCS
  25. * @see \Drupal\bootstrap\Theme::IGNORE_DEV
  26. */
  27. const IGNORE_DEFAULT = -1;
  28. /**
  29. * Ignores the directories "assets", "css", "images" and "js".
  30. */
  31. const IGNORE_ASSETS = 0x1;
  32. /**
  33. * Ignores the directories "config", "lib" and "src".
  34. */
  35. const IGNORE_CORE = 0x2;
  36. /**
  37. * Ignores the directories "docs" and "documentation".
  38. */
  39. const IGNORE_DOCS = 0x4;
  40. /**
  41. * Ignores "bower_components", "grunt", "node_modules" and "starterkits".
  42. */
  43. const IGNORE_DEV = 0x8;
  44. /**
  45. * Ignores the directories "templates" and "theme".
  46. */
  47. const IGNORE_TEMPLATES = 0x16;
  48. /**
  49. * Flag indicating if the theme is Bootstrap based.
  50. *
  51. * @var bool
  52. */
  53. protected $bootstrap;
  54. /**
  55. * A list of available CDN Provider instances.
  56. *
  57. * @var \Drupal\bootstrap\Plugin\Provider\ProviderInterface[]
  58. */
  59. protected $cdnProviders;
  60. /**
  61. * Flag indicating if the theme is in "development" mode.
  62. *
  63. * @var bool
  64. *
  65. * This property can only be set via `settings.local.php`:
  66. *
  67. * @code
  68. * $settings['theme.dev'] = TRUE;
  69. * @endcode
  70. */
  71. protected $dev;
  72. /**
  73. * The current theme info.
  74. *
  75. * @var array
  76. */
  77. protected $info;
  78. /**
  79. * A URL for where a livereload instance is listening, if set.
  80. *
  81. * @var string
  82. *
  83. * This property can only be set via `settings.local.php`:
  84. *
  85. * @code
  86. * // Enable default value: //127.0.0.1:35729/livereload.js.
  87. * $settings['theme.livereload'] = TRUE;
  88. *
  89. * // Or, set just the port number: //127.0.0.1:12345/livereload.js.
  90. * $settings['theme.livereload'] = 12345;
  91. *
  92. * // Or, Set an explicit URL.
  93. * $settings['theme.livereload'] = '//127.0.0.1:35729/livereload.js';
  94. * @endcode
  95. */
  96. protected $livereload;
  97. /**
  98. * The theme machine name.
  99. *
  100. * @var string
  101. */
  102. protected $name;
  103. /**
  104. * An array of Setting instances.
  105. *
  106. * @var \Drupal\bootstrap\Plugin\Setting\SettingInterface[]
  107. */
  108. protected $settings;
  109. /**
  110. * The current theme Extension object.
  111. *
  112. * @var \Drupal\Core\Extension\Extension
  113. */
  114. protected $theme;
  115. /**
  116. * An array of installed themes.
  117. *
  118. * @var array
  119. */
  120. protected $themes;
  121. /**
  122. * Theme handler object.
  123. *
  124. * @var \Drupal\Core\Extension\ThemeHandlerInterface
  125. */
  126. protected $themeHandler;
  127. /**
  128. * The update plugin manager.
  129. *
  130. * @var \Drupal\bootstrap\Plugin\UpdateManager
  131. */
  132. protected $updateManager;
  133. /**
  134. * Theme constructor.
  135. *
  136. * @param \Drupal\Core\Extension\Extension $theme
  137. * A theme \Drupal\Core\Extension\Extension object.
  138. * @param \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler
  139. * The theme handler object.
  140. */
  141. public function __construct(Extension $theme, ThemeHandlerInterface $theme_handler) {
  142. // Determine if "development mode" is set.
  143. $this->dev = !!Settings::get('theme.dev');
  144. // Determine the URL for livereload, if set.
  145. $this->livereload = '';
  146. if ($livereload = Settings::get('theme.livereload')) {
  147. // If TRUE, then set the port to the default used by grunt-contrib-watch.
  148. if ($livereload === TRUE) {
  149. $livereload = '//127.0.0.1:35729/livereload.js';
  150. }
  151. // If an integer, assume it's a port.
  152. elseif (is_int($livereload)) {
  153. $livereload = "//127.0.0.1:$livereload/livereload.js";
  154. }
  155. // If it's scalar, attempt to parse the URL.
  156. elseif (is_scalar($livereload)) {
  157. try {
  158. $livereload = Url::fromUri($livereload)->toString();
  159. }
  160. catch (\Exception $e) {
  161. $livereload = '';
  162. }
  163. }
  164. // Typecast livereload URL to a string.
  165. $this->livereload = "$livereload" ?: '';
  166. }
  167. $this->name = $theme->getName();
  168. $this->theme = $theme;
  169. $this->themeHandler = $theme_handler;
  170. $this->themes = $this->themeHandler->listInfo();
  171. $this->info = isset($this->themes[$this->name]->info) ? $this->themes[$this->name]->info : [];
  172. $this->bootstrap = $this->subthemeOf('bootstrap');
  173. // Only install the theme if it's Bootstrap based and there are no schemas
  174. // currently set.
  175. if ($this->isBootstrap() && !$this->getSetting('schemas')) {
  176. try {
  177. $this->install();
  178. }
  179. catch (\Exception $e) {
  180. // Intentionally left blank.
  181. // @see https://www.drupal.org/node/2697075
  182. }
  183. }
  184. }
  185. /**
  186. * Serialization method.
  187. */
  188. public function __sleep() {
  189. // Only store the theme name.
  190. return ['name'];
  191. }
  192. /**
  193. * Unserialize method.
  194. */
  195. public function __wakeup() {
  196. $theme_handler = Bootstrap::getThemeHandler();
  197. $theme = $theme_handler->getTheme($this->name);
  198. $this->__construct($theme, $theme_handler);
  199. }
  200. /**
  201. * Returns the theme machine name.
  202. *
  203. * @return string
  204. * Theme machine name.
  205. */
  206. public function __toString() {
  207. return $this->getName();
  208. }
  209. /**
  210. * Retrieves the theme's settings array appropriate for drupalSettings.
  211. *
  212. * @return array
  213. * The theme settings for drupalSettings.
  214. */
  215. public function drupalSettings() {
  216. // Immediately return if theme is not Bootstrap based.
  217. if (!$this->isBootstrap()) {
  218. return [];
  219. }
  220. $cache = $this->getCache('drupalSettings');
  221. $drupal_settings = $cache->getAll();
  222. if (!$drupal_settings) {
  223. foreach ($this->getSettingPlugin() as $name => $setting) {
  224. if ($setting->drupalSettings()) {
  225. $drupal_settings[$name] = TRUE;
  226. }
  227. }
  228. $cache->setMultiple($drupal_settings);
  229. }
  230. $drupal_settings = array_intersect_key($this->settings()->get(), $drupal_settings);
  231. // Indicate that theme is in dev mode.
  232. if ($this->isDev()) {
  233. $drupal_settings['dev'] = TRUE;
  234. }
  235. return $drupal_settings;
  236. }
  237. /**
  238. * Wrapper for the core file_scan_directory() function.
  239. *
  240. * Finds all files that match a given mask in the given directories and then
  241. * caches the results. A general site cache clear will force new scans to be
  242. * initiated for already cached directories.
  243. *
  244. * @param string $mask
  245. * The preg_match() regular expression of the files to find.
  246. * @param string $subdir
  247. * Sub-directory in the theme to start the scan, without trailing slash. If
  248. * not set, the base path of the current theme will be used.
  249. * @param array $options
  250. * Options to pass, see file_scan_directory() for addition options:
  251. * - ignore_flags: (int|FALSE) A bitmask to indicate which directories (if
  252. * any) should be skipped during the scan. Must also not contain a
  253. * "nomask" property in $options. Value can be any of the following:
  254. * - \Drupal\bootstrap::IGNORE_CORE
  255. * - \Drupal\bootstrap::IGNORE_ASSETS
  256. * - \Drupal\bootstrap::IGNORE_DOCS
  257. * - \Drupal\bootstrap::IGNORE_DEV
  258. * - \Drupal\bootstrap::IGNORE_THEME
  259. * Pass FALSE to iterate over all directories in $dir.
  260. *
  261. * @return array
  262. * An associative array (keyed on the chosen key) of objects with 'uri',
  263. * 'filename', and 'name' members corresponding to the matching files.
  264. *
  265. * @see file_scan_directory()
  266. */
  267. public function fileScan($mask, $subdir = NULL, array $options = []) {
  268. $path = $this->getPath();
  269. // Append addition sub-directories to the path if they were provided.
  270. if (isset($subdir)) {
  271. $path .= '/' . $subdir;
  272. }
  273. // Default ignore flags.
  274. $options += [
  275. 'ignore_flags' => self::IGNORE_DEFAULT,
  276. ];
  277. $flags = $options['ignore_flags'];
  278. if ($flags === self::IGNORE_DEFAULT) {
  279. $flags = self::IGNORE_CORE | self::IGNORE_ASSETS | self::IGNORE_DOCS | self::IGNORE_DEV;
  280. }
  281. // Save effort by skipping directories that are flagged.
  282. if (!isset($options['nomask']) && $flags) {
  283. $ignore_directories = [];
  284. if ($flags & self::IGNORE_ASSETS) {
  285. $ignore_directories += ['assets', 'css', 'images', 'js'];
  286. }
  287. if ($flags & self::IGNORE_CORE) {
  288. $ignore_directories += ['config', 'lib', 'src'];
  289. }
  290. if ($flags & self::IGNORE_DOCS) {
  291. $ignore_directories += ['docs', 'documentation'];
  292. }
  293. if ($flags & self::IGNORE_DEV) {
  294. $ignore_directories += [
  295. 'bower_components',
  296. 'grunt',
  297. 'node_modules',
  298. 'starterkits',
  299. ];
  300. }
  301. if ($flags & self::IGNORE_TEMPLATES) {
  302. $ignore_directories += ['templates', 'theme'];
  303. }
  304. if (!empty($ignore_directories)) {
  305. $options['nomask'] = '/^' . implode('|', $ignore_directories) . '$/';
  306. }
  307. }
  308. // Retrieve cache.
  309. $files = $this->getCache('files');
  310. // Generate a unique hash for all parameters passed as a change in any of
  311. // them could potentially return different results.
  312. $hash = Crypt::generateBase64HashIdentifier($options, [$mask, $path]);
  313. if (!$files->has($hash)) {
  314. $files->set($hash, file_scan_directory($path, $mask, $options));
  315. }
  316. return $files->get($hash, []);
  317. }
  318. /**
  319. * Retrieves the full base/sub-theme ancestry of a theme.
  320. *
  321. * @param bool $reverse
  322. * Whether or not to return the array of themes in reverse order, where the
  323. * active theme is the first entry.
  324. *
  325. * @return \Drupal\bootstrap\Theme[]
  326. * An associative array of \Drupal\bootstrap objects (theme), keyed
  327. * by machine name.
  328. */
  329. public function getAncestry($reverse = FALSE) {
  330. $ancestry = $this->themeHandler->getBaseThemes($this->themes, $this->getName());
  331. foreach (array_keys($ancestry) as $name) {
  332. $ancestry[$name] = Bootstrap::getTheme($name, $this->themeHandler);
  333. }
  334. $ancestry[$this->getName()] = $this;
  335. return $reverse ? array_reverse($ancestry) : $ancestry;
  336. }
  337. /**
  338. * Retrieves an individual item from a theme's cache in the database.
  339. *
  340. * @param string $name
  341. * The name of the item to retrieve from the theme cache.
  342. * @param array $context
  343. * Optional. An array of additional context to use for retrieving the
  344. * cached storage.
  345. * @param mixed $default
  346. * Optional. The default value to use if $name does not exist.
  347. *
  348. * @return mixed|\Drupal\bootstrap\Utility\StorageItem
  349. * The cached value for $name.
  350. */
  351. public function getCache($name, array $context = [], $default = []) {
  352. static $cache = [];
  353. // Prepend the theme name as the first context item, followed by cache name.
  354. array_unshift($context, $name);
  355. array_unshift($context, $this->getName());
  356. // Join context together with ":" and use it as the name.
  357. $name = implode(':', $context);
  358. if (!isset($cache[$name])) {
  359. $storage = self::getStorage();
  360. $value = $storage->get($name);
  361. if (!isset($value)) {
  362. $value = is_array($default) ? new StorageItem($default, $storage) : $default;
  363. $storage->set($name, $value);
  364. }
  365. $cache[$name] = $value;
  366. }
  367. return $cache[$name];
  368. }
  369. /**
  370. * Retrieves the set CDN Provider instance for the theme.
  371. *
  372. * @return \Drupal\bootstrap\Plugin\Provider\ProviderInterface
  373. * A CDN Provider instance.
  374. */
  375. public function getCdnProvider() {
  376. $provider = $this->getSetting('cdn_provider');
  377. $providers = $this->getCdnProviders();
  378. return isset($providers[$provider]) ? $providers[$provider] : ProviderManager::broken();
  379. }
  380. /**
  381. * Retrieves all available CDN Provider instances.
  382. *
  383. * @return \Drupal\bootstrap\Plugin\Provider\ProviderInterface[]
  384. * All CDN Provider instances.
  385. */
  386. public function getCdnProviders() {
  387. if (!isset($this->cdnProviders)) {
  388. $this->cdnProviders = [];
  389. // Only continue if the theme is Bootstrap based.
  390. if ($this->isBootstrap()) {
  391. $provider_manager = new ProviderManager($this);
  392. foreach ($provider_manager->getDefinitions() as $provider => $definition) {
  393. // Ignore hidden providers.
  394. if (!empty($definition['hidden'])) {
  395. continue;
  396. }
  397. $this->cdnProviders[$provider] = $provider_manager->get($provider, ['theme' => $this]);
  398. }
  399. }
  400. }
  401. return $this->cdnProviders;
  402. }
  403. /**
  404. * Retrieves the theme info.
  405. *
  406. * @param string $property
  407. * A specific property entry from the theme's info array to return.
  408. *
  409. * @return array
  410. * The entire theme info or a specific item if $property was passed.
  411. */
  412. public function getInfo($property = NULL) {
  413. if (isset($property)) {
  414. return isset($this->info[$property]) ? $this->info[$property] : NULL;
  415. }
  416. return $this->info;
  417. }
  418. /**
  419. * Returns the machine name of the theme.
  420. *
  421. * @return string
  422. * The machine name of the theme.
  423. */
  424. public function getName() {
  425. return $this->theme->getName();
  426. }
  427. /**
  428. * Returns the relative path of the theme.
  429. *
  430. * @return string
  431. * The relative path of the theme.
  432. */
  433. public function getPath() {
  434. return $this->theme->getPath();
  435. }
  436. /**
  437. * Retrieves pending updates for the theme.
  438. *
  439. * @return \Drupal\bootstrap\Plugin\Update\UpdateInterface[]
  440. * An array of update plugin objects.
  441. */
  442. public function getPendingUpdates() {
  443. $pending = [];
  444. // Only continue if the theme is Bootstrap based.
  445. if ($this->isBootstrap()) {
  446. $current_theme = $this->getName();
  447. $schemas = $this->getSetting('schemas', []);
  448. foreach ($this->getAncestry() as $ancestor) {
  449. $ancestor_name = $ancestor->getName();
  450. if (!isset($schemas[$ancestor_name])) {
  451. $schemas[$ancestor_name] = \Drupal::CORE_MINIMUM_SCHEMA_VERSION;
  452. $this->setSetting('schemas', $schemas);
  453. }
  454. $pending_updates = $ancestor->getUpdateManager()->getPendingUpdates($current_theme === $ancestor_name);
  455. foreach ($pending_updates as $schema => $update) {
  456. if ((int) $schema > (int) $schemas[$ancestor_name]) {
  457. $pending[] = $update;
  458. }
  459. }
  460. }
  461. }
  462. return $pending;
  463. }
  464. /**
  465. * Retrieves a theme setting.
  466. *
  467. * @param string $name
  468. * The name of the setting to be retrieved.
  469. * @param mixed $default
  470. * A default value to provide if the setting is not found or if the plugin
  471. * does not have a "defaultValue" annotation key/value pair. Typically,
  472. * you will likely never need to use this unless in rare circumstances
  473. * where the setting plugin exists but needs a default value not able to
  474. * be set by conventional means (e.g. empty array).
  475. *
  476. * @return mixed
  477. * The value of the requested setting, NULL if the setting does not exist
  478. * and no $default value was provided.
  479. *
  480. * @see theme_get_setting()
  481. */
  482. public function getSetting($name, $default = NULL) {
  483. $value = $this->settings()->get($name);
  484. return !isset($value) ? $default : $value;
  485. }
  486. /**
  487. * Retrieves a theme's setting plugin instance(s).
  488. *
  489. * @param string $name
  490. * Optional. The name of a specific setting plugin instance to return.
  491. * @param bool $rebuild
  492. * Flag indicating whether to reset any cached definitions and rebuild
  493. * the settings.
  494. *
  495. * @return \Drupal\bootstrap\Plugin\Setting\SettingInterface|\Drupal\bootstrap\Plugin\Setting\SettingInterface[]|null
  496. * If $name was provided, it will either return a specific setting plugin
  497. * instance or NULL if not set. If $name was omitted it will return an array
  498. * of setting plugin instances, keyed by their name.
  499. */
  500. public function getSettingPlugin($name = NULL, $rebuild = FALSE) {
  501. if (!isset($this->settings) || $rebuild) {
  502. $settings = [];
  503. if ($this->isBootstrap()) {
  504. $setting_manager = new SettingManager($this);
  505. if ($rebuild) {
  506. $setting_manager->clearCachedDefinitions();
  507. }
  508. $plugin_ids = array_keys($setting_manager->getDefinitions());
  509. foreach ($plugin_ids as $plugin_id) {
  510. $settings[$plugin_id] = $setting_manager->createInstance($plugin_id);
  511. }
  512. }
  513. $this->settings = $settings;
  514. }
  515. // Return a specific setting plugin.
  516. if (isset($name)) {
  517. return isset($this->settings[$name]) ? $this->settings[$name] : NULL;
  518. }
  519. // Return all setting plugins.
  520. return $this->settings;
  521. }
  522. /**
  523. * Retrieves the theme's cache from the database.
  524. *
  525. * @return \Drupal\bootstrap\Utility\Storage
  526. * The cache object.
  527. */
  528. public function getStorage() {
  529. static $cache = [];
  530. $theme = $this->getName();
  531. if (!isset($cache[$theme])) {
  532. $cache[$theme] = new Storage($theme);
  533. }
  534. return $cache[$theme];
  535. }
  536. /**
  537. * Retrieves the human-readable title of the theme.
  538. *
  539. * @return string
  540. * The theme title or machine name as a fallback.
  541. */
  542. public function getTitle() {
  543. return $this->getInfo('name') ?: $this->getName();
  544. }
  545. /**
  546. * Retrieves the update plugin manager for the theme.
  547. *
  548. * @return \Drupal\bootstrap\Plugin\UpdateManager|false
  549. * The Update plugin manager or FALSE if theme is not Bootstrap based.
  550. */
  551. public function getUpdateManager() {
  552. // Immediately return if theme is not Bootstrap based.
  553. if (!$this->isBootstrap()) {
  554. return FALSE;
  555. }
  556. if (!$this->updateManager) {
  557. $this->updateManager = new UpdateManager($this);
  558. }
  559. return $this->updateManager;
  560. }
  561. /**
  562. * Determines whether or not if the theme has Bootstrap Framework Glyphicons.
  563. */
  564. public function hasGlyphicons() {
  565. $glyphicons = $this->getCache('glyphicons');
  566. if (!$glyphicons->has($this->getName())) {
  567. $exists = FALSE;
  568. foreach ($this->getAncestry(TRUE) as $ancestor) {
  569. if ($ancestor->getSetting('cdn_provider') || $ancestor->fileScan('/glyphicons-halflings-regular\.(eot|svg|ttf|woff)$/', NULL, ['ignore_flags' => FALSE])) {
  570. $exists = TRUE;
  571. break;
  572. }
  573. }
  574. $glyphicons->set($this->getName(), $exists);
  575. }
  576. return $glyphicons->get($this->getName(), FALSE);
  577. }
  578. /**
  579. * Includes a file from the theme.
  580. *
  581. * @param string $file
  582. * The file name, including the extension.
  583. * @param string $path
  584. * The path to the file in the theme. Defaults to: "includes". Set to FALSE
  585. * or and empty string if the file resides in the theme's root directory.
  586. *
  587. * @return bool
  588. * TRUE if the file exists and is included successfully, FALSE otherwise.
  589. */
  590. public function includeOnce($file, $path = 'includes') {
  591. static $includes = [];
  592. $file = preg_replace('`^/?' . $this->getPath() . '/?`', '', $file);
  593. $file = strpos($file, '/') !== 0 ? $file = "/$file" : $file;
  594. $path = is_string($path) && !empty($path) && strpos($path, '/') !== 0 ? $path = "/$path" : '';
  595. $include = DRUPAL_ROOT . '/' . $this->getPath() . $path . $file;
  596. if (!isset($includes[$include])) {
  597. $includes[$include] = [email protected]include_once $include;
  598. if (!$includes[$include]) {
  599. Bootstrap::message(t('Could not include file: @include', ['@include' => $include]), 'error');
  600. }
  601. }
  602. return $includes[$include];
  603. }
  604. /**
  605. * Installs a Bootstrap based theme.
  606. */
  607. protected function install() {
  608. // Immediately return if theme is not Bootstrap based.
  609. if (!$this->isBootstrap()) {
  610. return;
  611. }
  612. $schemas = [];
  613. foreach ($this->getAncestry() as $ancestor) {
  614. $schemas[$ancestor->getName()] = $ancestor->getUpdateManager()->getLatestSchema();
  615. }
  616. $this->setSetting('schemas', $schemas);
  617. }
  618. /**
  619. * Indicates whether the theme is bootstrap based.
  620. *
  621. * @return bool
  622. * TRUE or FALSE
  623. */
  624. public function isBootstrap() {
  625. return $this->bootstrap;
  626. }
  627. /**
  628. * Indicates whether the theme is in "development mode".
  629. *
  630. * @return bool
  631. * TRUE or FALSE
  632. *
  633. * @see \Drupal\bootstrap\Theme::dev
  634. */
  635. public function isDev() {
  636. return $this->dev;
  637. }
  638. /**
  639. * Returns the livereload URL set, if any.
  640. *
  641. * @see \Drupal\bootstrap\Theme::livereload
  642. *
  643. * @return string
  644. * The livereload URL.
  645. */
  646. public function livereloadUrl() {
  647. return $this->livereload;
  648. }
  649. /**
  650. * Removes a theme setting.
  651. *
  652. * @param string $name
  653. * Name of the theme setting to remove.
  654. */
  655. public function removeSetting($name) {
  656. $this->settings()->clear($name)->save();
  657. }
  658. /**
  659. * Sets a value for a theme setting.
  660. *
  661. * @param string $name
  662. * Name of the theme setting.
  663. * @param mixed $value
  664. * Value to associate with the theme setting.
  665. */
  666. public function setSetting($name, $value) {
  667. $this->settings()->set($name, $value)->save();
  668. }
  669. /**
  670. * Retrieves the theme settings instance.
  671. *
  672. * @return \Drupal\bootstrap\ThemeSettings
  673. * All settings.
  674. */
  675. public function settings() {
  676. static $themes = [];
  677. $name = $this->getName();
  678. if (!isset($themes[$name])) {
  679. $themes[$name] = new ThemeSettings($this);
  680. }
  681. return $themes[$name];
  682. }
  683. /**
  684. * Determines whether or not a theme is a sub-theme of another.
  685. *
  686. * @param string|\Drupal\bootstrap\Theme $theme
  687. * The name or theme Extension object to check.
  688. *
  689. * @return bool
  690. * TRUE or FALSE
  691. */
  692. public function subthemeOf($theme) {
  693. return (string) $theme === $this->getName() || in_array($theme, array_keys(self::getAncestry()));
  694. }
  695. /****************************************************************************
  696. *
  697. * Deprecated methods
  698. *
  699. ***************************************************************************/
  700. /**
  701. * Retrieves the CDN Provider.
  702. *
  703. * @param string $provider
  704. * Optional. A CDN Provider name. If not set, defaults to the CDN
  705. * provider set in the theme settings.
  706. *
  707. * @return \Drupal\bootstrap\Plugin\Provider\ProviderInterface|false
  708. * A provider instance or FALSE if no provider is set.
  709. *
  710. * @deprecated in 8.x-3.18, will be removed in a future release.
  711. *
  712. * @see \Drupal\bootstrap\Theme::getCdnProvider()
  713. * @see \Drupal\bootstrap\Plugin\ProviderManager::load()
  714. */
  715. public function getProvider($provider = NULL) {
  716. $provider = $provider ?: $this->getSetting('cdn_provider');
  717. $providers = $this->getProviders();
  718. if (!isset($providers[$provider])) {
  719. return FALSE;
  720. }
  721. return $providers[$provider];
  722. }
  723. /**
  724. * Retrieves all CDN Providers.
  725. *
  726. * @return \Drupal\bootstrap\Plugin\Provider\ProviderInterface[]
  727. * All provider instances.
  728. *
  729. * @deprecated in 8.x-3.18, will be removed in a future release.
  730. *
  731. * @see \Drupal\bootstrap\Theme::getCdnProviders()
  732. */
  733. public function getProviders() {
  734. return !$this->isBootstrap() ? [] : $this->getCdnProviders();
  735. }
  736. /**
  737. * Retrieves the theme's setting plugin instances.
  738. *
  739. * @return \Drupal\bootstrap\Plugin\Setting\SettingInterface[]
  740. * An associative array of setting objects, keyed by their name.
  741. *
  742. * @deprecated in 8.x-3.1, will be removed in a future release.
  743. *
  744. * @see \Drupal\bootstrap\Theme::getSettingPlugin()
  745. */
  746. public function getSettingPlugins() {
  747. Bootstrap::deprecated();
  748. return $this->getSettingPlugin();
  749. }
  750. }

Classes

Name Description
Theme Defines a theme object.