Completed
Pull Request — master (#114)
by Bart
09:14
created

Base   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 28.13%

Importance

Changes 0
Metric Value
wmc 18
lcom 1
cbo 5
dl 0
loc 144
ccs 9
cts 32
cp 0.2813
rs 10
c 0
b 0
f 0

8 Methods

Rating   Name   Duplication   Size   Complexity  
A behaviors() 0 7 1
getRecords() 0 1 ?
A export() 0 9 3
B getRecordDefinition() 0 25 4
C import() 0 27 7
A importError() 0 9 3
saveRecord() 0 1 ?
deleteRecord() 0 1 ?
1
<?php
2
3
namespace NerdsAndCompany\Schematic\Services;
4
5
use craft\base\Model;
6
use yii\base\Component as BaseComponent;
7
use NerdsAndCompany\Schematic\Behaviors\FieldLayoutBehavior;
8
use NerdsAndCompany\Schematic\Behaviors\SourcesBehavior;
9
use NerdsAndCompany\Schematic\Interfaces\MappingInterface;
10
use NerdsAndCompany\Schematic\Schematic;
11
use LogicException;
12
13
/**
14
 * Schematic Base Service.
15
 *
16
 * Sync Craft Setups.
17
 *
18
 * @author    Nerds & Company
19
 * @copyright Copyright (c) 2015-2018, Nerds & Company
20
 * @license   MIT
21
 *
22
 * @see      http://www.nerds.company
23
 */
24
abstract class Base extends BaseComponent implements MappingInterface
25
{
26
    /**
27
     * Load fieldlayout and sources behaviors
28
     *
29
     * @return array
30
     */
31
    public function behaviors()
32
    {
33
        return [
34
          FieldLayoutBehavior::className(),
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
35
          SourcesBehavior::className(),
0 ignored issues
show
Deprecated Code introduced by
The method yii\base\BaseObject::className() has been deprecated with message: since 2.0.14. On PHP >=5.5, use `::class` instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
36
        ];
37
    }
38
39
    /**
40
     * Get all records
41
     *
42
     * @return Model[]
43
     */
44
    abstract protected function getRecords();
45
46
    //==============================================================================================================
47 57
    //================================================  EXPORT  ====================================================
48
    //==============================================================================================================
49 57
50 57
    /**
51
     * Get all record definitions
52
     *
53
     * @return array
54
     */
55
    public function export(array $records = null)
56
    {
57
        $records = $records ?: $this->getRecords();
58
        $result = [];
59
        foreach ($records as $record) {
60
            $result[$record->handle] = $this->getRecordDefinition($record);
61
        }
62
        return $result;
63
    }
64
65
    /**
66
     * Get single record definition
67
     *
68
     * @param  Model $record
69
     * @return array
70
     */
71
    protected function getRecordDefinition(Model $record)
72
    {
73
        $definition = [
74
          'class' => get_class($record),
75
          'attributes' => $record->attributes,
76
        ];
77
        unset($definition['attributes']['id']);
78
        unset($definition['attributes']['dateCreated']);
79
        unset($definition['attributes']['dateUpdated']);
80
81
        if (isset($definition['attributes']['sources'])) {
82
            $definition['sources'] = $this->getSources($definition['class'], $definition['attributes']['sources'], 'id', 'handle');
0 ignored issues
show
Documentation Bug introduced by
The method getSources does not exist on object<NerdsAndCompany\Schematic\Services\Base>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
83
        }
84
85
        if (isset($definition['attributes']['source'])) {
86
            $definition['source'] = $this->getSource($definition['class'], $definition['attributes']['sources'], 'id', 'handle');
0 ignored issues
show
Documentation Bug introduced by
The method getSource does not exist on object<NerdsAndCompany\Schematic\Services\Base>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
87
        }
88
89
        if (isset($definition['attributes']['fieldLayoutId'])) {
90
            $definition['fieldLayout'] = $this->getFieldLayoutDefinition($record->getFieldLayout());
0 ignored issues
show
Documentation Bug introduced by
The method getFieldLayoutDefinition does not exist on object<NerdsAndCompany\Schematic\Services\Base>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
91
            unset($definition['attributes']['fieldLayoutId']);
92
        }
93
94
        return $definition;
95
    }
96
97
    //==============================================================================================================
98
    //================================================  IMPORT  ====================================================
99
    //==============================================================================================================
100
101
    /**
102
     * Import asset volumes.
103
     *
104
     * @param array $definitions
105
     * @param bool  $force
106
     */
107
    public function import(array $definitions, $force = false)
108
    {
109
        $recordsByHandle = [];
110
        foreach ($this->getRecords() as $record) {
111
            $recordsByHandle[$record->handle] = $record;
112
        }
113 4
114
        foreach ($definitions as $handle => $definition) {
115 4
            $record = new $definition['class']();
116 4
            if (array_key_exists($handle, $recordsByHandle)) {
117
                $record = $recordsByHandle[$handle];
118
            }
119
            Schematic::info('Importing record '.$handle);
120
            if (!$this->saveRecord($record, $definition)) {
121
                $this->importError($record, $handle);
122
            }
123
            unset($recordsByHandle[$handle]);
124 11
        }
125
126 11
        if ($force) {
127 11
            // Delete volumes not in definitions
128
            foreach ($recordsByHandle as $handle => $record) {
129
                Schematic::info('Deleting record '.$handle);
130
                $this->deleteRecord($record);
131
            }
132
        }
133
    }
134
135
    /**
136
     * Log an import error
137
     *
138
     * @param  Model $record
139
     * @param  string $handle
140
     */
141
    protected function importError($record, $handle)
142
    {
143
        Schematic::warning('Error importing record '.$handle);
144
        foreach ($record->getErrors() as $errors) {
145
            foreach ($errors as $error) {
146
                Schematic::error($error);
147
            }
148
        }
149
    }
150
151
    /**
152
     * Save a record
153
     *
154
     * @param Model $record
155
     * @param array $definition
156
     * @return boolean
157
     */
158
    abstract protected function saveRecord(Model $record, array $definition);
159
160
    /**
161
     * Delete a record
162
     *
163
     * @param Model $record
164
     * @return boolean
165
     */
166
    abstract protected function deleteRecord(Model $record);
167
}
168