Issues (83)

src/services/Loader.php (10 issues)

1
<?php
2
/**
3
 * Spoon plugin for Craft CMS 3.x
4
 *
5
 * Enhance Matrix
6
 *
7
 * @link      https://angell.io
8
 * @copyright Copyright (c) 2018 Angell & Co
9
 */
10
11
namespace angellco\spoon\services;
12
13
use angellco\spoon\assetbundles\ConfiguratorAsset;
14
use angellco\spoon\assetbundles\FieldManipulatorAsset;
15
use angellco\spoon\Spoon;
16
17
use Craft;
18
use craft\base\Component;
19
use craft\helpers\Db;
20
use craft\helpers\Json;
21
use craft\models\Section;
22
use yii\base\InvalidConfigException;
23
24
/**
25
 * Loader methods
26
 *
27
 * @author    Angell & Co
28
 * @package   Spoon
29
 * @since     3.0.0
30
 */
31
class Loader extends Component
32
{
33
34
    /**
35
     * Loads the configurator and field manipulator code in all the
36
     * core supported contexts as well as providing a hook for
37
     * third-party contexts.
38
     *
39
     * @throws InvalidConfigException
40
     */
41
    public function run()
42
    {
43
        $request = Craft::$app->getRequest();
44
45
        // Check the conditions are right to run
46
        if ($request->getIsCpRequest() && !$request->getAcceptsJson())
47
        {
48
49
            $segments = Craft::$app->request->getSegments();
50
            $entries = Craft::$app->getEntries();
51
52
            /**
53
             * Check third party plugin support
54
             */
55
            $commercePlugin = Craft::$app->plugins->getPlugin('commerce');
56
            $calendarPlugin = Craft::$app->plugins->getPlugin('calendar');
57
58
            /**
59
             * Work out the context for the block type groups configuration
60
             */
61
            // Entry types
62
            if (\count($segments) === 5
63
                && $segments[0] === 'settings'
64
                && $segments[1] === 'sections'
65
                && $segments[3] === 'entrytypes'
66
                && $segments[4] !== 'new'
67
            )
68
            {
69
                $uid = Db::uidById('{{%entrytypes}}', $segments[4]);
70
                $this->configurator('#fieldlayoutform', 'entrytype:'.$uid);
71
            }
72
73
            // Category groups
74
            if (\count($segments) === 3
75
                && $segments[0] === 'settings'
76
                && $segments[1] === 'categories'
77
                && $segments[2] !== 'new'
78
            )
79
            {
80
                $uid = Db::uidById('{{%categorygroups}}', $segments[2]);
81
                $this->configurator('#fieldlayoutform', 'categorygroup:'.$uid);
82
            }
83
84
            // Global sets
85
            if (\count($segments) === 3
86
                && $segments[0] === 'settings'
87
                && $segments[1] === 'globals'
88
                && $segments[2] !== 'new'
89
            )
90
            {
91
                $uid = Db::uidById('{{%globalsets}}', $segments[2]);
92
                $this->configurator('#fieldlayoutform', 'globalset:'.$uid);
93
            }
94
95
            // Users
96
            if (\count($segments) === 2
97
                && $segments[0] === 'settings'
98
                && $segments[1] === 'users'
99
            )
100
            {
101
                $this->configurator('#fieldlayoutform', 'users');
102
            }
103
104
            // Solpace Calendar
105
            if (\count($segments) === 3
106
                && $segments[0] === 'calendar'
107
                && $segments[1] === 'calendars'
108
                && $segments[2] !== 'new'
109
                && $calendarPlugin
110
            )
111
            {
112
                $calendarService = new \Solspace\Calendar\Services\CalendarsService();
0 ignored issues
show
The type Solspace\Calendar\Services\CalendarsService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
113
                if ($calendarService) {
0 ignored issues
show
$calendarService is of type Solspace\Calendar\Services\CalendarsService, thus it always evaluated to true.
Loading history...
114
                    $calendar = $calendarService->getCalendarByHandle(end($segments));
115
                    if ($calendar) {
116
                        $uid = Db::uidById(\Solspace\Calendar\Records\CalendarRecord::TABLE, $calendar->id);
0 ignored issues
show
The type Solspace\Calendar\Records\CalendarRecord was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
117
                        $this->configurator('#fieldlayoutform', 'calendar:'.$uid);
118
                    }
119
                }
120
            }
121
122
            // Commerce
123
            if (\count($segments) === 4
124
                && $segments[0] === 'commerce'
125
                && $segments[1] === 'settings'
126
                && $segments[2] === 'producttypes'
127
                && $segments[3] !== 'new'
128
                && $commercePlugin
129
            ) {
130
                $productTypesService = new \craft\commerce\services\ProductTypes();
0 ignored issues
show
The type craft\commerce\services\ProductTypes was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
131
                if ($productTypesService) {
0 ignored issues
show
$productTypesService is of type craft\commerce\services\ProductTypes, thus it always evaluated to true.
Loading history...
132
                    $productType = $productTypesService->getProductTypeById($segments[3]);
133
                    if ($productType) {
134
                        $this->configurator('#fieldlayoutform', 'producttype:'.$productType->uid);
135
                    }
136
                }
137
            }
138
139
            /**
140
             * Work out the context for the Matrix field manipulation
141
             */
142
            // Global
143
            $context = 'global';
144
            $versioned = false;
145
146
            // Entry types
147
            if (\count($segments) >= 3 && $segments[0] === 'entries') {
148
149
                if ($segments[2] === 'new') {
150
                    /** @var Section $section */
151
                    $section = Craft::$app->getSections()->getSectionByHandle($segments[1]);
152
                    $sectionEntryTypes = $section->getEntryTypes();
153
                    $entryType = reset($sectionEntryTypes);
154
                } else {
155
                    $entryId = (integer)explode('-', $segments[2])[0];
156
157
                    // Check if we have a site handle in the URL
158
                    if (isset($segments[3])) {
159
                        // If we do, get the site and fetch the entry with it
160
                        $site = Craft::$app->getSites()->getSiteByHandle($segments[3]);
161
                        $entry = $entries->getEntryById($entryId, $site !== null ? $site->id : null);
162
                    } else {
163
                        $entry = $entries->getEntryById($entryId);
164
                    }
165
166
                    if ($entry)
0 ignored issues
show
$entry is of type craft\elements\Entry, thus it always evaluated to true.
Loading history...
167
                    {
168
                        $entryType = $entry->type;
169
                    }
170
                }
171
172
                $revisionId = $request->getParam('revisionId');
173
                if ($revisionId) {
174
                    $versioned = true;
175
                }
176
177
                if (isset($entryType) && $entryType) {
178
                    $context = 'entrytype:'.$entryType->uid;
179
                }
180
181
            }
182
            // Category groups
183
            else if (\count($segments) >= 3 && $segments[0] === 'categories')
184
            {
185
                $group = Craft::$app->getCategories()->getGroupByHandle($segments[1]);
186
                if ($group)
187
                {
188
                    $context = 'categorygroup:'.$group->uid;
189
                }
190
            }
191
            // Global sets
192
            else if (\count($segments) >= 2 && $segments[0] === 'globals')
193
            {
194
                $set = Craft::$app->getGlobals()->getSetByHandle(end($segments));
195
                if ($set)
196
                {
197
                    $context = 'globalset:'.$set->uid;
198
                }
199
            }
200
            // Users
201
            else if ((\count($segments) === 1 && $segments[0] === 'myaccount') || (\count($segments) == 2 && $segments[0] === 'users'))
202
            {
203
                $context = 'users';
204
            }
205
            // Solspace Calendar
206
            else if (\count($segments) >= 4
207
                && $segments[0] === 'calendar'
208
                && $segments[1] === 'events'
209
                && $calendarPlugin
210
            ) {
211
212
                if ($segments[2] === 'new') {
213
                    $calendarService = new \Solspace\Calendar\Services\CalendarsService();
214
                    $calendar = $calendarService->getCalendarByHandle($segments[3]);
215
                    if ($calendar) {
216
                        $uid = Db::uidById(\Solspace\Calendar\Records\CalendarRecord::TABLE, $calendar->id);
217
                        $context = 'calendar:'.$uid;
218
                    }
219
                } else {
220
                    $calendarEventsService = new \Solspace\Calendar\Services\EventsService();
0 ignored issues
show
The type Solspace\Calendar\Services\EventsService was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
221
                    if ($calendarEventsService) {
0 ignored issues
show
$calendarEventsService is of type Solspace\Calendar\Services\EventsService, thus it always evaluated to true.
Loading history...
222
                        $event = $calendarEventsService->getEventById($segments[2]);
223
                        if ($event) {
224
                            $uid = Db::uidById(\Solspace\Calendar\Records\CalendarRecord::TABLE, $event->getCalendar()->id);
225
                            $context = 'calendar:'.$uid;
226
                        }
227
                    }
228
                }
229
            }
230
            // Commerce
231
            else if (\count($segments) >= 3
232
                && $segments[0] === 'commerce'
233
                && $segments[1] === 'products'
234
                && $commercePlugin
235
            ) {
236
                $productTypesService = new \craft\commerce\services\ProductTypes();
237
                if ($productTypesService) {
0 ignored issues
show
$productTypesService is of type craft\commerce\services\ProductTypes, thus it always evaluated to true.
Loading history...
238
                    $productType = $productTypesService->getProductTypeByHandle($segments[2]);
239
                    if ($productType) {
240
                        $context = 'producttype:'.$productType->uid;
241
                    }
242
                }
243
            }
244
245
            // Run the field manipulation code
246
            $this->fieldManipulator($context, $versioned);
247
248
        }
249
250
    }
251
252
    /**
253
     * Loads a Spoon.Configurator() for the correct context
254
     *
255
     * @param $container
256
     * @param $context
257
     *
258
     * @throws InvalidConfigException
259
     */
260
    public function configurator($container, $context)
261
    {
262
263
        $view = Craft::$app->getView();
264
265
        $view->registerAssetBundle(ConfiguratorAsset::class);
266
267
        $settings = [
268
            'matrixFieldIds' => Spoon::$plugin->fields->getMatrixFieldIds(),
269
            'context' => $context
270
        ];
271
272
        $view->registerJs('new Spoon.Configurator("'.$container.'", '.Json::encode($settings, JSON_UNESCAPED_UNICODE).');');
273
274
    }
275
276
    /**
277
     * Loads a Spoon.FieldManipulator() for the correct context
278
     *
279
     * @param      $context
280
     * @param bool $versioned
281
     *
282
     * @throws InvalidConfigException
283
     */
284
    public function fieldManipulator($context, $versioned = false)
285
    {
286
        // Get global data
287
        $globalSpoonedBlockTypes = Spoon::$plugin->blockTypes->getByContext('global', 'context');
288
289
        // Get all the data for the entrytype context regardless of entrytype id
290
        $mainContext = explode(':', $context)[0];
291
        $contextSpoonedBlockTypes = Spoon::$plugin->blockTypes->getByContext($mainContext, 'context', true);
292
293
        $spoonedBlockTypes = array_merge($globalSpoonedBlockTypes, $contextSpoonedBlockTypes);
294
295
        if ($spoonedBlockTypes)
0 ignored issues
show
Bug Best Practice introduced by
The expression $spoonedBlockTypes of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
296
        {
297
            $view = Craft::$app->getView();
298
299
            $view->registerAssetBundle(FieldManipulatorAsset::class);
300
301
            $translations = [];
302
303
            foreach ($spoonedBlockTypes as $spoonedBlockTypesInContext) {
304
                foreach ($spoonedBlockTypesInContext as $spoonedBlockType) {
305
                    $translations[] = $spoonedBlockType->groupName;
306
                    $translations[] = $spoonedBlockType->matrixBlockType->name;
307
308
                    if ($spoonedBlockType->fieldLayoutModel) {
309
                        foreach ($spoonedBlockType->fieldLayoutModel['tabs'] as $tab) {
310
                            $translations[] = $tab->name;
311
                        }
312
                    }
313
314
                }
315
            }
316
317
            $view->registerTranslations('site', $translations);
318
319
            $settings = [
320
                'blockTypes' => $spoonedBlockTypes,
321
                'context' => $context,
322
                'versioned' => $versioned,
323
                'nestedSettingsHandles' => Spoon::$plugin->getSettings()->nestedSettings
324
            ];
325
326
            $view->registerJs('if (typeof Craft.MatrixInput !== "undefined") { Spoon.fieldmanipulator = new Spoon.FieldManipulator('.Json::encode($settings, JSON_UNESCAPED_UNICODE).') };');
327
        }
328
329
    }
330
331
}
332