Updated Drupal to 8.6. This goes with the following updates because it's possible...
[yaffs-website] / web / core / lib / Drupal / Core / Menu / StaticMenuLinkOverrides.php
1 <?php
2
3 namespace Drupal\Core\Menu;
4
5 use Drupal\Core\Config\ConfigFactoryInterface;
6
7 /**
8  * Defines an implementation of the menu link override using a config file.
9  */
10 class StaticMenuLinkOverrides implements StaticMenuLinkOverridesInterface {
11
12   /**
13    * The config name used to store the overrides.
14    *
15    * This configuration can not be overridden by configuration overrides because
16    * menu links and these overrides are cached in a way that is not override
17    * aware.
18    *
19    * @var string
20    */
21   protected $configName = 'core.menu.static_menu_link_overrides';
22
23   /**
24    * The menu link overrides config object.
25    *
26    * @var \Drupal\Core\Config\Config
27    */
28   protected $config;
29
30   /**
31    * The config factory object.
32    *
33    * @var \Drupal\Core\Config\ConfigFactoryInterface
34    */
35   protected $configFactory;
36
37   /**
38    * Constructs a StaticMenuLinkOverrides object.
39    *
40    * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
41    *   A configuration factory instance.
42    */
43   public function __construct(ConfigFactoryInterface $config_factory) {
44     $this->configFactory = $config_factory;
45   }
46
47   /**
48    * Gets the configuration object when needed.
49    *
50    * Since this service is injected into all static menu link objects, but
51    * only used when updating one, avoid actually loading the config when it's
52    * not needed.
53    */
54   protected function getConfig() {
55     if (empty($this->config)) {
56       // Get an override free and editable configuration object.
57       $this->config = $this->configFactory->getEditable($this->configName);
58     }
59     return $this->config;
60   }
61
62   /**
63    * {@inheritdoc}
64    */
65   public function reload() {
66     $this->config = NULL;
67     $this->configFactory->reset($this->configName);
68   }
69
70   /**
71    * {@inheritdoc}
72    */
73   public function loadOverride($id) {
74     $all_overrides = $this->getConfig()->get('definitions');
75     $id = static::encodeId($id);
76     return $id && isset($all_overrides[$id]) ? $all_overrides[$id] : [];
77   }
78
79   /**
80    * {@inheritdoc}
81    */
82   public function deleteMultipleOverrides(array $ids) {
83     $all_overrides = $this->getConfig()->get('definitions');
84     $save = FALSE;
85     foreach ($ids as $id) {
86       $id = static::encodeId($id);
87       if (isset($all_overrides[$id])) {
88         unset($all_overrides[$id]);
89         $save = TRUE;
90       }
91     }
92     if ($save) {
93       $this->getConfig()->set('definitions', $all_overrides)->save();
94     }
95     return $save;
96   }
97
98   /**
99    * {@inheritdoc}
100    */
101   public function deleteOverride($id) {
102     return $this->deleteMultipleOverrides([$id]);
103   }
104
105   /**
106    * {@inheritdoc}
107    */
108   public function loadMultipleOverrides(array $ids) {
109     $result = [];
110     if ($ids) {
111       $all_overrides = $this->getConfig()->get('definitions') ?: [];
112       foreach ($ids as $id) {
113         $encoded_id = static::encodeId($id);
114         if (isset($all_overrides[$encoded_id])) {
115           $result[$id] = $all_overrides[$encoded_id];
116         }
117       }
118     }
119     return $result;
120   }
121
122   /**
123    * {@inheritdoc}
124    */
125   public function saveOverride($id, array $definition) {
126     // Only allow to override a specific subset of the keys.
127     $expected = [
128       'menu_name' => '',
129       'parent' => '',
130       'weight' => 0,
131       'expanded' => FALSE,
132       'enabled' => FALSE,
133     ];
134     // Filter the overrides to only those that are expected.
135     $definition = array_intersect_key($definition, $expected);
136     // Ensure all values are set.
137     $definition = $definition + $expected;
138     if ($definition) {
139       // Cast keys to avoid config schema during save.
140       $definition['menu_name'] = (string) $definition['menu_name'];
141       $definition['parent'] = (string) $definition['parent'];
142       $definition['weight'] = (int) $definition['weight'];
143       $definition['expanded'] = (bool) $definition['expanded'];
144       $definition['enabled'] = (bool) $definition['enabled'];
145
146       $id = static::encodeId($id);
147       $all_overrides = $this->getConfig()->get('definitions');
148       // Combine with any existing data.
149       $all_overrides[$id] = $definition + $this->loadOverride($id);
150       $this->getConfig()->set('definitions', $all_overrides)->save(TRUE);
151     }
152     return array_keys($definition);
153   }
154
155   /**
156    * {@inheritdoc}
157    */
158   public function getCacheTags() {
159     return $this->getConfig()->getCacheTags();
160   }
161
162   /**
163    * Encodes the ID by replacing dots with double underscores.
164    *
165    * This is done because config schema uses dots for its internal type
166    * hierarchy. Double underscores are converted to triple underscores to
167    * avoid accidental conflicts.
168    *
169    * @param string $id
170    *   The menu plugin ID.
171    *
172    * @return string
173    *   The menu plugin ID with double underscore instead of dots.
174    */
175   protected static function encodeId($id) {
176     return strtr($id, ['.' => '__', '__' => '___']);
177   }
178
179 }