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