Completed
Push — master ( 280b95...97ab68 )
by Bart
9s
created

SourcesBehavior::findSources()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.4888
c 0
b 0
f 0
cc 5
nc 5
nop 4
crap 5
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Behaviors;
4
5
use Craft;
6
use TypeError;
7
use yii\base\Behavior;
8
use craft\base\Model;
9
use NerdsAndCompany\Schematic\Schematic;
10
use NerdsAndCompany\Schematic\Events\SourceMappingEvent;
11
12
/**
13
 * Schematic Sources Behavior.
14
 *
15
 * Sync Craft Setups.
16
 *
17
 * @author    Nerds & Company
18
 * @copyright Copyright (c) 2015-2018, Nerds & Company
19
 * @license   MIT
20
 *
21
 * @see      http://www.nerds.company
22
 */
23
class SourcesBehavior extends Behavior
24
{
25
    /**
26
     * Recursively find sources in definition attributes.
27
     *
28
     * @param string $fieldType
29
     * @param array  $attributes
30
     * @param string $indexFrom
31
     * @param string $indexTo
32
     *
33
     * @return array
34
     */
35 32
    public function findSources(string $fieldType, array $attributes, string $indexFrom, string $indexTo): array
36
    {
37 32
        foreach ($attributes as $key => $attribute) {
38 32
            if ($key === 'source') {
39 4
                $attributes[$key] = $this->getSource($fieldType, $attribute, $indexFrom, $indexTo);
40 32
            } elseif ($key === 'sources') {
41 4
                $attributes[$key] = $this->getSources($fieldType, $attribute, $indexFrom, $indexTo);
42 32
            } elseif (is_array($attribute)) {
43 32
                $attributes[$key] = $this->findSources($fieldType, $attribute, $indexFrom, $indexTo);
44
            }
45
        }
46
47 32
        return $attributes;
48
    }
49
50
    /**
51
     * Get sources based on the indexFrom attribute and return them with the indexTo attribute.
52
     *
53
     * @param string       $fieldType
54
     * @param string|array $sources
55
     * @param string       $indexFrom
56
     * @param string       $indexTo
57
     *
58
     * @return array|string
59
     */
60 9
    public function getSources(string $fieldType, $sources, string $indexFrom, string $indexTo)
61
    {
62 9
        $mappedSources = $sources;
63 9
        if (is_array($sources)) {
64 7
            $mappedSources = [];
65 7
            $sources = array_filter($sources);
66 7
            foreach ($sources as $source) {
67 7
                $mappedSources[] = $this->getSource($fieldType, $source, $indexFrom, $indexTo);
68
            }
69
        }
70
71 9
        return $mappedSources;
72
    }
73
74
    /**
75
     * Gets a source by the attribute indexFrom, and returns it with attribute $indexTo.
76
     *
77
     * @TODO Break up and simplify this method
78
     *
79
     * @param string $fieldType
80
     * @param string $source
81
     * @param string $indexFrom
82
     * @param string $indexTo
83
     *
84
     * @return string|null
85
     *
86
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
87
     * @SuppressWarnings(PHPMD.NPathComplexity)
88
     */
89 9
    public function getSource(string $fieldType, string $source = null, string $indexFrom, string $indexTo)
90
    {
91 9
        if (false === strpos($source, ':')) {
92 7
            return $source;
93
        }
94
95
        /** @var Model $sourceObject */
96 9
        $sourceObject = null;
97
98
        // Get service and method by source
99 9
        list($sourceType, $sourceFrom) = explode(':', $source);
100 9
        switch ($sourceType) {
101 9
            case 'editSite':
102
                $service = Craft::$app->sites;
103
                $method = 'getSiteBy';
104
                break;
105 9
            case 'single':
106 9
            case 'section':
107 9
            case 'createEntries':
108 9
            case 'editPeerEntries':
109 9
            case 'deleteEntries':
110 9
            case 'deletePeerEntries':
111 9
            case 'deletePeerEntryDrafts':
112 9
            case 'editEntries':
113 9
            case 'editPeerEntryDrafts':
114 9
            case 'publishEntries':
115 9
            case 'publishPeerEntries':
116 9
            case 'publishPeerEntryDrafts':
117 5
                $service = Craft::$app->sections;
118 5
                $method = 'getSectionBy';
119 5
                break;
120 9
            case 'group':
121 7
            case 'editCategories':
122 5
                $service = 'Users' == $fieldType ? Craft::$app->userGroups : Craft::$app->categories;
123 5
                $method = 'getGroupBy';
124 5
                break;
125 7
            case 'folder':
126 5
            case 'createFoldersInVolume':
127 5
            case 'deleteFilesAndFoldersInVolume':
128 5
            case 'saveAssetInVolume':
129 5
            case 'viewVolume':
130 5
                $service = Craft::$app->volumes;
131 5
                $method = 'getVolumeBy';
132 5
                break;
133 2
            case 'taggroup':
134
                $service = Craft::$app->tags;
135
                $method = 'getTagGroupBy';
136
                break;
137 2
            case 'field':
138 2
                $service = Craft::$app->fields;
139 2
                $method = 'getFieldBy';
140 2
                break;
141
            case 'editGlobalSet':
142
                $service = Craft::$app->globals;
143
                $method = 'getSetBy';
144
                break;
145
            case 'utility':
146
                return $source;
147
        }
148
149
        // Send event
150 9
        $plugin = Craft::$app->controller->module;
151 9
        $event = new SourceMappingEvent([
152 9
            'source' => $source,
153 9
            'service' => $service ?? null,
154 9
            'method' => $method ?? null,
155
        ]);
156 9
        $plugin->trigger($plugin::EVENT_MAP_SOURCE, $event);
157 9
        $service = $event->service;
158 9
        $method = $event->method;
159
160
        // Try service and method
161 9
        if (isset($service) && isset($method) && isset($sourceFrom)) {
162 9
            $method = $method.ucfirst($indexFrom);
163
            try {
164 9
                $sourceObject = $service->$method($sourceFrom);
0 ignored issues
show
Bug introduced by
The method $method cannot be called on $service (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
165
            } catch (TypeError $e) {
166
                Schematic::error('An error occured mapping source '.$source.' from '.$indexFrom.' to '.$indexTo);
167
                Schematic::error($e->getMessage());
168
169
                return null;
170
            }
171
        }
172
173 9
        if ($sourceObject) {
174 8
            return $sourceType.':'.$sourceObject->$indexTo;
175
        }
176
177 1
        Schematic::warning('No mapping found for source '.$source);
178
179 1
        return null;
180
    }
181
}
182