Failed Conditions
Pull Request — master (#26)
by Bob Olde
07:33
created

src/services/Sections.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace NerdsAndCompany\Schematic\Services;
4
5
use Craft\Craft;
6
use Craft\SectionRecord;
7
use Craft\SectionModel;
8
use Craft\SectionLocaleModel;
9
use Craft\EntryTypeModel;
10
11
/**
12
 * Schematic Result Model.
13
 *
14
 * Sync Craft Setups.
15
 *
16
 * @author    Nerds & Company
17
 * @copyright Copyright (c) 2015, Nerds & Company
18
 * @license   MIT
19
 *
20
 * @link      http://www.nerds.company
21
 */
22
class Sections extends Base
23
{
24
    /**
25
     * Export sections.
26
     *
27
     * @param SectionModel[] $sections
28
     * @param array|null     $allowedEntryTypeIds
29
     *
30
     * @return array
31
     */
32
    public function export(array $sections = [], array $allowedEntryTypeIds = null)
33
    {
34
        Craft::log(Craft::t('Exporting Sections'));
35
36
        $sectionDefinitions = [];
37
38
        foreach ($sections as $section) {
39
            $sectionDefinitions[$section->handle] = $this->getSectionDefinition($section, $allowedEntryTypeIds);
40
        }
41
42
        return $sectionDefinitions;
43
    }
44
45
    /**
46
     * Get section definition.
47
     *
48
     * @param SectionModel $section
49
     * @param $allowedEntryTypeIds
50
     *
51
     * @return array
52
     */
53
    private function getSectionDefinition(SectionModel $section, $allowedEntryTypeIds)
54
    {
55
        return [
56
            'name' => $section->name,
57
            'type' => $section->type,
58
            'hasUrls' => $section->hasUrls,
59
            'template' => $section->template,
60
            'maxLevels' => $section->maxLevels,
61
            'enableVersioning' => $section->enableVersioning,
62
            'locales' => $this->getLocaleDefinitions($section->getLocales()),
63
            'entryTypes' => $this->getEntryTypeDefinitions($section->getEntryTypes(), $allowedEntryTypeIds),
64
        ];
65
    }
66
67
    /**
68
     * Get locale definitions.
69
     *
70
     * @param SectionLocaleModel[] $locales
71
     *
72
     * @return array
73
     */
74
    private function getLocaleDefinitions(array $locales)
75
    {
76
        $localeDefinitions = [];
77
78
        foreach ($locales as $locale) {
79
            $localeDefinitions[$locale->locale] = $this->getLocaleDefinition($locale);
80
        }
81
82
        return $localeDefinitions;
83
    }
84
85
    /**
86
     * Get locale definition.
87
     *
88
     * @param SectionLocaleModel $locale
89
     *
90
     * @return array
91
     */
92
    private function getLocaleDefinition(SectionLocaleModel $locale)
93
    {
94
        return [
95
            'enabledByDefault' => $locale->enabledByDefault,
96
            'urlFormat' => $locale->urlFormat,
97
            'nestedUrlFormat' => $locale->nestedUrlFormat,
98
        ];
99
    }
100
101
    /**
102
     * Get entry type definitions.
103
     *
104
     * @param array $entryTypes
105
     * @param $allowedEntryTypeIds
106
     *
107
     * @return array
108
     */
109
    private function getEntryTypeDefinitions(array $entryTypes, $allowedEntryTypeIds)
110
    {
111
        $entryTypeDefinitions = [];
112
113
        foreach ($entryTypes as $entryType) {
114
            if ($allowedEntryTypeIds === null || in_array($entryType->id, $allowedEntryTypeIds)) {
115
                $entryTypeDefinitions[$entryType->handle] = $this->getEntryTypeDefinition($entryType);
116
            }
117
        }
118
119
        return $entryTypeDefinitions;
120
    }
121
122
    /**
123
     * Get entry type definition.
124
     *
125
     * @param EntryTypeModel $entryType
126
     *
127
     * @return array
128
     */
129
    private function getEntryTypeDefinition(EntryTypeModel $entryType)
130
    {
131
        return [
132
            'name' => $entryType->name,
133
            'hasTitleField' => $entryType->hasTitleField,
134
            'titleLabel' => $entryType->titleLabel,
135
            'titleFormat' => $entryType->titleFormat,
136
            'fieldLayout' => Craft::app()->schematic_fields->getFieldLayoutDefinition($entryType->getFieldLayout()),
137
        ];
138
    }
139
140
    /**
141
     * Attempt to import sections.
142
     *
143
     * @param array $sectionDefinitions
144
     * @param bool  $force              If set to true sections not included in the import will be deleted
145
     *
146
     * @return Result
147
     */
148
    public function import(array $sectionDefinitions, $force = false)
149
    {
150
        Craft::log(Craft::t('Importing Sections'));
151
152
        $sections = Craft::app()->sections->getAllSections('handle');
153
154
        foreach ($sectionDefinitions as $sectionHandle => $sectionDefinition) {
155
            $section = array_key_exists($sectionHandle, $sections)
156
                ? $sections[$sectionHandle]
157
                : new SectionModel();
158
159
            unset($sections[$sectionHandle]);
160
161
            if (!array_key_exists('locales', $sectionDefinition)) {
162
                $this->addError('`sections[handle].locales` must be defined');
163
164
                continue;
165
            }
166
167
            if (!array_key_exists('entryTypes', $sectionDefinition)) {
168
                $this->addError('errors', '`sections[handle].entryTypes` must exist be defined');
169
170
                continue;
171
            }
172
173
            $this->populateSection($section, $sectionDefinition, $sectionHandle);
174
175
            // Create initial section record
176
            if (!$this->preSaveSection($section)) {
177
                $this->addErrors($section->getAllErrors());
178
179
                continue;
180
            }
181
182
            $entryTypes = $section->getEntryTypes('handle');
183
184
            foreach ($sectionDefinition['entryTypes'] as $entryTypeHandle => $entryTypeDefinition) {
185
                $entryType = array_key_exists($entryTypeHandle, $entryTypes)
186
                    ? $entryTypes[$entryTypeHandle]
187
                    : new EntryTypeModel();
188
189
                $this->populateEntryType($entryType, $entryTypeDefinition, $entryTypeHandle, $section->id);
190
191
                if (!Craft::app()->sections->saveEntryType($entryType)) {
192
                    $this->addError($entryType->getAllErrors());
193
194
                    continue;
195
                }
196
            }
197
198
            // Save section via craft after entrytypes have been created
199
            if (!Craft::app()->sections->saveSection($section)) {
200
                $this->addErrors($section->getAllErrors());
201
            }
202
        }
203
204
        if ($force) {
205
            foreach ($sections as $section) {
206
                Craft::app()->sections->deleteSectionById($section->id);
207
            }
208
        }
209
210
        return $this->getResultModel();
211
    }
212
213
    /**
214
     * Save the section manually if it is new to prevent craft from creating the default entry type
215
     * In case of a single we do want the default entry type and do a normal save
216
     * Todo: This method is a bit hackish, find a better way.
217
     *
218
     * @param SectionModel $section
219
     *
220
     * @return mixed
221
     */
222
    private function preSaveSection(SectionModel $section)
223
    {
224
        if ($section->type != 'single' && !$section->id) {
225
            $sectionRecord = new SectionRecord();
226
227
            // Shared attributes
228
            $sectionRecord->name = $section->name;
229
            $sectionRecord->handle = $section->handle;
230
            $sectionRecord->type = $section->type;
231
            $sectionRecord->enableVersioning = $section->enableVersioning;
232
233
            if (!$sectionRecord->save()) {
234
                $section->addErrors(['errors' => $sectionRecord->getErrors(]));
0 ignored issues
show
This code did not parse for me. Apparently, there is an error somewhere around this line:

Syntax error, unexpected ']'
Loading history...
235
236
                return false;
237
            };
238
            $section->id = $sectionRecord->id;
239
240
            return true;
241
        }
242
243
        return Craft::app()->sections->saveSection($section);
244
    }
245
246
    /**
247
     * Populate section.
248
     *
249
     * @param SectionModel $section
250
     * @param array        $sectionDefinition
251
     * @param string       $sectionHandle
252
     */
253
    private function populateSection(SectionModel $section, array $sectionDefinition, $sectionHandle)
254
    {
255
        $section->setAttributes([
256
            'handle' => $sectionHandle,
257
            'name' => $sectionDefinition['name'],
258
            'type' => $sectionDefinition['type'],
259
            'hasUrls' => $sectionDefinition['hasUrls'],
260
            'template' => $sectionDefinition['template'],
261
            'maxLevels' => $sectionDefinition['maxLevels'],
262
            'enableVersioning' => $sectionDefinition['enableVersioning'],
263
        ]);
264
265
        $this->populateSectionLocales($section, $sectionDefinition['locales']);
266
    }
267
268
    /**
269
     * Populate section locales.
270
     *
271
     * @param SectionModel $section
272
     * @param $localeDefinitions
273
     */
274
    private function populateSectionLocales(SectionModel $section, $localeDefinitions)
275
    {
276
        $locales = $section->getLocales();
277
278
        foreach ($localeDefinitions as $localeId => $localeDef) {
279
            $locale = array_key_exists($localeId, $locales) ? $locales[$localeId] : new SectionLocaleModel();
280
281
            $locale->setAttributes([
282
                'locale' => $localeId,
283
                'enabledByDefault' => $localeDef['enabledByDefault'],
284
                'urlFormat' => $localeDef['urlFormat'],
285
                'nestedUrlFormat' => $localeDef['nestedUrlFormat'],
286
            ]);
287
288
            // Todo: Is this a hack? I don't see another way.
289
            // Todo: Might need a sorting order as well? It's NULL at the moment.
290
            Craft::app()->db->createCommand()->insertOrUpdate('locales', [
291
                'locale' => $locale->locale,
292
            ], []);
293
294
            $locales[$localeId] = $locale;
295
        }
296
297
        $section->setLocales($locales);
298
    }
299
300
    /**
301
     * Populate entry type.
302
     *
303
     * @param EntryTypeModel $entryType
304
     * @param array          $entryTypeDefinition
305
     * @param string         $entryTypeHandle
306
     * @param int            $sectionId
307
     */
308
    private function populateEntryType(EntryTypeModel $entryType, array $entryTypeDefinition, $entryTypeHandle, $sectionId)
309
    {
310
        $entryType->setAttributes([
311
            'handle' => $entryTypeHandle,
312
            'sectionId' => $sectionId,
313
            'name' => $entryTypeDefinition['name'],
314
            'hasTitleField' => $entryTypeDefinition['hasTitleField'],
315
            'titleLabel' => $entryTypeDefinition['titleLabel'],
316
            'titleFormat' => $entryTypeDefinition['titleFormat'],
317
        ]);
318
319
        $fieldLayout = Craft::app()->schematic_fields->getFieldLayout($entryTypeDefinition['fieldLayout']);
320
        $entryType->setFieldLayout($fieldLayout);
321
    }
322
}
323