Completed
Branch FET/asset-manager (433489)
by
unknown
32:42 queued 18:11
created

CollectionLoader   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 282
Duplicated Lines 6.38 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
dl 18
loc 282
rs 10
c 0
b 0
f 0
wmc 24
lcom 1
cbo 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 14 2
A getCollection() 0 4 1
B loadAllFromFilepaths() 0 22 4
A loadClassFromFilepath() 0 18 4
B addEntityToCollection() 18 35 3
B setIdentifier() 0 39 5
A loadFromFQCNs() 0 13 2
A loadClassFromFQCN() 0 13 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
namespace EventEspresso\core\services\collections;
4
5
use EventEspresso\core\exceptions\InvalidClassException;
6
use EventEspresso\core\exceptions\InvalidDataTypeException;
7
use EventEspresso\core\exceptions\InvalidEntityException;
8
use EventEspresso\core\exceptions\InvalidFilePathException;
9
use EventEspresso\core\services\locators\LocatorInterface;
10
use EventEspresso\core\services\locators\FileLocator;
11
12
/**
13
 * Class CollectionLoader
14
 * given the details on where to find files, will populate a collection
15
 * plz see: \EventEspresso\core\services\collections\CollectionDetails
16
 *
17
 * @package       Event Espresso
18
 * @author        Brent Christensen
19
 * @since         4.9.0
20
 */
21
class CollectionLoader
22
{
23
24
    /**
25
     * possible return value when adding entities to a collection.
26
     * denotes that the entity was NOT ADDED to the collection
27
     */
28
    const ENTITY_NOT_ADDED = 'entity-not-added-to-collection';
29
30
    /**
31
     * possible return value when adding entities to a collection.
32
     * denotes that the entity was SUCCESSFULLY ADDED to the collection
33
     */
34
    const ENTITY_ADDED = 'entity-added-to-collection';
35
36
    /**
37
     * possible return value when adding entities to a collection.
38
     * denotes that the entity was ALREADY ADDED to the collection,
39
     * and therefore could not be added again.
40
     */
41
    const ENTITY_EXISTS = 'entity-already-in-collection';
42
43
44
    /**
45
     * @var CollectionDetailsInterface $collection_details
46
     */
47
    protected $collection_details;
48
49
    /**
50
     * @var CollectionInterface $collection
51
     */
52
    protected $collection;
53
54
    /**
55
     * @var FileLocator $file_locator
56
     */
57
    protected $file_locator;
58
59
60
    /**
61
     * CollectionLoader constructor.
62
     *
63
     * @param CollectionDetailsInterface $collection_details
64
     * @param CollectionInterface        $collection
65
     * @param LocatorInterface           $file_locator
66
     * @throws \EventEspresso\core\exceptions\InvalidInterfaceException
67
     * @throws \EventEspresso\core\exceptions\InvalidClassException
68
     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
69
     * @throws \EventEspresso\core\exceptions\InvalidFilePathException
70
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
71
     */
72
    public function __construct(
73
        CollectionDetailsInterface $collection_details,
74
        CollectionInterface $collection = null,
75
        LocatorInterface $file_locator = null
76
    ) {
77
        $this->collection_details = $collection_details;
78
        if (! $collection instanceof CollectionInterface) {
79
            $collection = new Collection($this->collection_details->getCollectionInterface());
80
        }
81
        $this->collection = $collection;
82
        $this->file_locator = $file_locator;
83
        $this->loadAllFromFilepaths();
84
        $this->loadFromFQCNs();
85
    }
86
87
88
    /**
89
     * @access public
90
     * @return \EventEspresso\core\services\collections\CollectionInterface
91
     */
92
    public function getCollection()
93
    {
94
        return $this->collection;
95
    }
96
97
98
    /**
99
     * @access protected
100
     * @throws \EventEspresso\core\exceptions\InvalidClassException
101
     * @throws \EventEspresso\core\exceptions\InvalidFilePathException
102
     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
103
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
104
     */
105
    protected function loadAllFromFilepaths()
106
    {
107
        if (! $this->file_locator instanceof FileLocator) {
108
            $this->file_locator = new FileLocator();
109
        }
110
        $this->file_locator->setFileMask($this->collection_details->getFileMask());
111
        // find all of the files that match the file mask in the specified folder
112
        $this->file_locator->locate($this->collection_details->getCollectionPaths());
113
        // filter the results
114
        $filepaths = (array) apply_filters(
115
            'FHEE__CollectionLoader__loadAllFromFilepath__filepaths',
116
            $this->file_locator->getFilePaths(),
117
            $this->collection_details->collectionName(),
118
            $this->collection_details
119
        );
120
        if (empty($filepaths)) {
121
            return;
122
        }
123
        foreach ($filepaths as $filepath) {
124
            $this->loadClassFromFilepath($filepath);
125
        }
126
    }
127
128
129
    /**
130
     * loadClassFromFilepath
131
     *
132
     * @access protected
133
     * @param  string $filepath
134
     * @return string
135
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
136
     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
137
     * @throws \EventEspresso\core\exceptions\InvalidFilePathException
138
     * @throws \EventEspresso\core\exceptions\InvalidClassException
139
     */
140
    protected function loadClassFromFilepath($filepath)
141
    {
142
        if (! is_string($filepath)) {
143
            throw new InvalidDataTypeException('$filepath', $filepath, 'string');
144
        }
145
        if (! is_readable($filepath)) {
146
            throw new InvalidFilePathException($filepath);
147
        }
148
        require_once($filepath);
149
        // extract filename from path
150
        $file_name = basename($filepath);
151
        // now remove any file extensions
152
        $class_name = \EEH_File::get_classname_from_filepath_with_standard_filename($file_name);
153
        if (! class_exists($class_name)) {
154
            throw new InvalidClassException($class_name);
155
        }
156
        return $this->addEntityToCollection(new $class_name(), $file_name);
157
    }
158
159
160
    /**
161
     * addEntityToCollection
162
     *
163
     * @access protected
164
     * @param        $entity
165
     * @param  mixed $identifier
166
     * @return string
167
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
168
     */
169
    protected function addEntityToCollection($entity, $identifier)
170
    {
171
        do_action(
172
            'FHEE__CollectionLoader__addEntityToCollection__entity',
173
            $entity,
174
            $this->collection_details->collectionName(),
175
            $this->collection_details
176
        );
177
        $identifier = $this->setIdentifier($entity, $identifier);
178 View Code Duplication
        if ($this->collection->has($identifier)) {
179
            do_action(
180
                'FHEE__CollectionLoader__addEntityToCollection__entity_already_added',
181
                $this,
182
                $this->collection_details->collectionName(),
183
                $this->collection_details
184
            );
185
            return CollectionLoader::ENTITY_EXISTS;
186
        }
187 View Code Duplication
        if ($this->collection->add($entity, $identifier)) {
188
            do_action(
189
                'FHEE__CollectionLoader__addEntityToCollection__entity_added',
190
                $this,
191
                $this->collection_details->collectionName(),
192
                $this->collection_details
193
            );
194
            return CollectionLoader::ENTITY_ADDED;
195
        }
196
        do_action(
197
            'FHEE__CollectionLoader__addEntityToCollection__entity_not_added',
198
            $this,
199
            $this->collection_details->collectionName(),
200
            $this->collection_details
201
        );
202
        return CollectionLoader::ENTITY_NOT_ADDED;
203
    }
204
205
206
    /**
207
     * setIdentifier
208
     *
209
     * @access protected
210
     * @param        $entity
211
     * @param  mixed $identifier
212
     * @return string
213
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
214
     */
215
    protected function setIdentifier($entity, $identifier)
216
    {
217
        switch ($this->collection_details->identifierType()) {
218
            // every unique object gets added to the collection, but not duplicates of the exact same object
219
            case CollectionDetails::ID_OBJECT_HASH:
220
                $identifier = spl_object_hash($entity);
221
                break;
222
            // only one entity per class can be added to collection, like a singleton
223
            case CollectionDetails::ID_CLASS_NAME:
224
                $identifier = get_class($entity);
225
                break;
226
            // objects added to the collection based on entity callback, so the entity itself decides
227
            case CollectionDetails::ID_CALLBACK_METHOD:
228
                $identifier_callback = $this->collection_details->identifierCallback();
229
                if (! method_exists($entity, $identifier_callback)) {
230
                    throw new InvalidEntityException(
231
                        $entity,
232
                        $this->collection_details->getCollectionInterface(),
233
                        sprintf(
234
                            __(
235
                                'The current collection is configured to use a method named "%1$s" when setting or retrieving objects. The supplied entity is an instance
236
                                of "%2$s", but does not contain this method.',
237
                                'event_espresso'
238
                            ),
239
                            $identifier_callback,
240
                            get_class($entity)
241
                        )
242
                    );
243
                }
244
                $identifier = $entity->{$identifier_callback}();
245
                break;
246
        }
247
        return apply_filters(
248
            'FHEE__CollectionLoader__addEntityToCollection__identifier',
249
            $identifier,
250
            $this->collection_details->collectionName(),
251
            $this->collection_details
252
        );
253
    }
254
255
256
    /**
257
     * loadFromFQCNs
258
     *
259
     * @access protected
260
     * @throws \EventEspresso\core\exceptions\InvalidClassException
261
     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
262
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
263
     */
264
    protected function loadFromFQCNs()
265
    {
266
        $FQCNs = $this->collection_details->getCollectionFQCNs();
267
        $FQCNs = (array) apply_filters(
268
            'FHEE__CollectionLoader__loadAllFromFQCNs__FQCNs',
269
            $FQCNs,
270
            $this->collection_details->collectionName(),
271
            $this->collection_details
272
        );
273
        foreach ($FQCNs as $FQCN) {
274
            $this->loadClassFromFQCN($FQCN);
275
        }
276
    }
277
278
279
    /**
280
     * loadClassFromFQCN
281
     *
282
     * @access protected
283
     * @param  string $FQCN Fully Qualified Class Name
284
     * @return string
285
     * @throws \EventEspresso\core\exceptions\InvalidEntityException
286
     * @throws \EventEspresso\core\exceptions\InvalidDataTypeException
287
     * @throws \EventEspresso\core\exceptions\InvalidClassException
288
     */
289
    protected function loadClassFromFQCN($FQCN)
290
    {
291
        if (! is_string($FQCN)) {
292
            throw new InvalidDataTypeException('$FQCN', $FQCN, 'string');
293
        }
294
        if (! class_exists($FQCN)) {
295
            throw new InvalidClassException($FQCN);
296
        }
297
        return $this->addEntityToCollection(
298
            \EE_Registry::instance()->create($FQCN),
299
            $FQCN
300
        );
301
    }
302
}
303