Completed
Push — master ( 8bfd3d...5e213d )
by Tim
11s
created

ClearMediaGalleryObserver   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 142
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 0%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 17
c 3
b 0
f 0
lcom 1
cbo 5
dl 0
loc 142
ccs 0
cts 77
cp 0
rs 10

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getProductMediaProcessor() 0 4 1
D process() 0 84 13
A getProductMediaGalleriesBySku() 0 4 1
A getImageTypes() 0 4 1
1
<?php
2
3
/**
4
 * TechDivision\Import\Product\Media\Observers\ClearMediaGalleryObserver
5
 *
6
 * NOTICE OF LICENSE
7
 *
8
 * This source file is subject to the Open Software License (OSL 3.0)
9
 * that is available through the world-wide-web at this URL:
10
 * http://opensource.org/licenses/osl-3.0.php
11
 *
12
 * PHP version 5
13
 *
14
 * @author    Tim Wagner <[email protected]>
15
 * @copyright 2016 TechDivision GmbH <[email protected]>
16
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
17
 * @link      https://github.com/techdivision/import-product-media
18
 * @link      http://www.techdivision.com
19
 */
20
21
namespace TechDivision\Import\Product\Media\Observers;
22
23
use TechDivision\Import\Product\Media\Utils\ColumnKeys;
24
use TechDivision\Import\Product\Media\Utils\MemberNames;
25
use TechDivision\Import\Product\Observers\AbstractProductImportObserver;
26
use TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface;
27
use TechDivision\Import\Product\Media\Utils\ConfigurationKeys;
28
29
/**
30
 * Observer that cleaned up a product's media gallery information.
31
 *
32
 * @author    Tim Wagner <[email protected]>
33
 * @copyright 2016 TechDivision GmbH <[email protected]>
34
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
35
 * @link      https://github.com/techdivision/import-product-media
36
 * @link      http://www.techdivision.com
37
 */
38
class ClearMediaGalleryObserver extends AbstractProductImportObserver
39
{
40
41
    /**
42
     * The product media processor instance.
43
     *
44
     * @var \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface
45
     */
46
    protected $productMediaProcessor;
47
48
    /**
49
     * Initialize the observer with the passed product media processor instance.
50
     *
51
     * @param \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface $productMediaProcessor The product media processor instance
52
     */
53
    public function __construct(ProductMediaProcessorInterface $productMediaProcessor)
54
    {
55
        $this->productMediaProcessor = $productMediaProcessor;
56
    }
57
58
    /**
59
     * Return's the product media processor instance.
60
     *
61
     * @return \TechDivision\Import\Product\Media\Services\ProductMediaProcessorInterface The product media processor instance
62
     */
63
    protected function getProductMediaProcessor()
64
    {
65
        return $this->productMediaProcessor;
66
    }
67
68
    /**
69
     * Process the observer's business logic.
70
     *
71
     * @return array The processed row
72
     */
73
    protected function process()
74
    {
75
76
        // query whether or not the media gallery has to be cleaned up
77
        if ($this->getSubject()->getConfiguration()->hasParam(ConfigurationKeys::CLEAN_UP_MEDIA_GALLERY) &&
78
            $this->getSubject()->getConfiguration()->getParam(ConfigurationKeys::CLEAN_UP_MEDIA_GALLERY)
79
        ) {
80
            // initialize the array for the actual images
81
            $actualImageNames = array();
82
83
            // iterate over the available image fields
84
            foreach (array_keys($this->getImageTypes()) as $imageColumnName) {
85
                if ($this->hasValue($imageColumnName) && !in_array($imageName = $this->getValue($imageColumnName), $actualImageNames)) {
86
                    $actualImageNames[] = $imageName;
87
                }
88
            }
89
90
            // query whether or not, we've additional images
91
            if ($additionalImages = $this->getValue(ColumnKeys::ADDITIONAL_IMAGES, null, array($this, 'explode'))) {
92
                foreach ($additionalImages as $additionalImageName) {
93
                    // do nothing if the image has already been added, e. g. it is the base image
94
                    if (in_array($additionalImageName, $actualImageNames)) {
95
                        continue;
96
                    }
97
98
                    // else, add the image to the array
99
                    $actualImageNames[] = $additionalImageName;
100
                }
101
            }
102
103
            // load the existing media gallery entities for the produdct with the given SKU
104
            $existingProductMediaGalleries = $this->getProductMediaProcessor()
105
                                                  ->getProductMediaGalleriesBySku($sku = $this->getValue(ColumnKeys::SKU));
106
107
            // remove the images that are NOT longer available in the CSV file
108
            foreach ($existingProductMediaGalleries as $existingProductMediaGallery) {
109
                // do nothing if the file still exists
110
                if (in_array($existingImageName = $existingProductMediaGallery[MemberNames::VALUE], $actualImageNames)) {
111
                    continue;
112
                }
113
114
                try {
115
                    // remove the old image from the database
116
                    $this->getProductMediaProcessor()
117
                         ->deleteProductMediaGallery(array(MemberNames::VALUE_ID => $existingProductMediaGallery[MemberNames::VALUE_ID]));
118
119
                    // log a debug message that the image has been removed
120
                    $this->getSubject()
121
                         ->getSystemLogger()
122
                         ->warning(
123
                             $this->getSubject()->appendExceptionSuffix(
124
                                 sprintf(
125
                                     'Successfully removed image "%s" from media gallery for product with SKU "%s"',
126
                                     $existingImageName,
127
                                     $sku
128
                                 )
129
                             )
130
                         );
131
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
132
                } catch (\Exception $e) {
133
                    // log a warning if debug mode has been enabled and the file is NOT available
134
                    if ($this->getSubject()->isDebugMode()) {
135
                        $this->getSubject()
136
                             ->getSystemLogger()
137
                             ->warning($this->getSubject()->appendExceptionSuffix($e->getMessage()));
138
                    } else {
139
                        throw $e;
140
                    }
141
                }
142
            }
143
144
            // log a message that the images has been cleaned-up
145
            $this->getSubject()
146
                 ->getSystemLogger()
147
                 ->debug(
148
                     $this->getSubject()->appendExceptionSuffix(
149
                         sprintf(
150
                             'Successfully cleaned-up media gallery for product with SKU "%s"',
151
                             $sku
152
                         )
153
                     )
154
                 );
155
        }
156
    }
157
158
    /**
159
     * Load's the product media gallery entities with the passed SKU.
160
     *
161
     * @param string $sku The SKU to load the media gallery entities for
162
     *
163
     * @return array The product media gallery entities
164
     */
165
    protected function getProductMediaGalleriesBySku($sku)
166
    {
167
        return $this->getProductMediaProcessor()->getProductMediaGalleriesBySku($sku);
168
    }
169
170
    /**
171
     * Return's the array with the available image types and their label columns.
172
     *
173
     * @return array The array with the available image types
174
     */
175
    protected function getImageTypes()
176
    {
177
        return $this->getSubject()->getImageTypes();
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface TechDivision\Import\Subjects\SubjectInterface as the method getImageTypes() does only exist in the following implementations of said interface: TechDivision\Import\Prod...a\Subjects\MediaSubject, TechDivision\Import\Prod...\AbstractProductSubject, TechDivision\Import\Product\Subjects\BunchSubject.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
178
    }
179
}
180