Passed
Push — v3 ( 58e9bb...917812 )
by Andrew
36:05 queued 26:33
created

SeoSettings::parseField()   B

Complexity

Conditions 7
Paths 13

Size

Total Lines 45
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
eloc 22
c 1
b 0
f 0
nc 13
nop 0
dl 0
loc 45
ccs 0
cts 32
cp 0
crap 56
rs 8.6346
1
<?php
2
/**
3
 * SEOmatic plugin for Craft CMS 3.x
4
 *
5
 * @link      https://nystudio107.com/
6
 * @copyright Copyright (c) 2020 nystudio107
7
 * @license   https://nystudio107.com/license
0 ignored issues
show
Coding Style introduced by
@license tag must contain a URL and a license name
Loading history...
8
 */
9
10
namespace nystudio107\seomatic\integrations\feedme;
11
12
use nystudio107\seomatic\fields\SeoSettings as SeoSettingsField;
13
14
use Craft;
15
use craft\db\Query;
16
use craft\db\Table;
17
use craft\elements\Asset as AssetElement;
18
use craft\helpers\ArrayHelper;
19
use craft\helpers\Db;
20
use craft\helpers\UrlHelper;
21
22
use craft\feedme\base\Field as FeedMeField;
0 ignored issues
show
Bug introduced by
The type craft\feedme\base\Field was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
23
use craft\feedme\base\FieldInterface as FeedMeFieldInterface;
0 ignored issues
show
Bug introduced by
The type craft\feedme\base\FieldInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
24
use craft\feedme\helpers\AssetHelper;
0 ignored issues
show
Bug introduced by
The type craft\feedme\helpers\AssetHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use craft\feedme\helpers\DataHelper;
0 ignored issues
show
Bug introduced by
The type craft\feedme\helpers\DataHelper was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
26
27
use Cake\Utility\Hash;
0 ignored issues
show
Bug introduced by
The type Cake\Utility\Hash was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
28
29
/**
30
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
31
 * @package   Seomatic
32
 * @since     3.3.0
33
 */
34
class SeoSettings extends FeedMeField implements FeedMeFieldInterface
35
{
36
    // Public Static Properties
37
    // =========================================================================
38
39
    public static $name = 'SEO Settings';
40
    public static $class = SeoSettingsField::class;
41
42
    // Public Methods
43
    // =========================================================================
44
45
    /**
46
     * @inheritDoc
47
     */
48
    public function getMappingTemplate()
49
    {
50
        return 'seomatic/_includes/integrations/feedme/seo-settings';
51
    }
52
53
    /**
54
     * @inheritDoc
55
     */
56
    public function parseField()
57
    {
58
        $preppedData = [];
59
60
        $fields = Hash::get($this->fieldInfo, 'fields');
61
62
        if (!$fields) {
63
            return null;
64
        }
65
66
        foreach ($fields as $subGroupHandle => $subGroup) {
67
            foreach ($subGroup as $subFieldHandle => $subFieldInfo) {
68
                $preppedData[$subGroupHandle][$subFieldHandle] = DataHelper::fetchValue($this->feedData, $subFieldInfo);
69
            }
70
        }
71
72
        // Protect against sending an empty array
73
        if (!$preppedData) {
74
            return null;
75
        }
76
77
        // Rip out asset related settings to place in `metaBundleSettings`
78
        $preppedData['metaBundleSettings'] = array_filter([
79
            'seoImageSource' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'seoImageSource'),
80
            'twitterImageSource' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'twitterImageSource'),
81
            'ogImageSource' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'ogImageSource'),
82
        ]);
83
84
        // Rip out asset images we need to upload or fetch as actual IDs
85
        $assetMappings = array_filter([
86
            'seoImageIds' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'seoImageIds'),
87
            'twitterImageIds' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'twitterImageIds'),
88
            'ogImageIds' => ArrayHelper::remove($preppedData['metaGlobalVars'], 'ogImageIds'),
89
        ]);
90
91
        // Handle image uploads
92
        foreach ($assetMappings as $key => $assetMapping) {
93
            $fieldInfo = Hash::get($this->fieldInfo, "fields.metaGlobalVars.{$key}");
94
95
            if ($assetIds = $this->parseImage($assetMapping, $fieldInfo)) {
96
                $preppedData['metaBundleSettings'][$key] = $assetIds;
97
            }
98
        }
99
100
        return $preppedData;
101
    }
102
103
    /**
104
     * @param $value
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
105
     * @param $fieldInfo
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
106
     * @return int|mixed|string|null
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
107
     * @throws \yii\base\Exception
0 ignored issues
show
Coding Style introduced by
Tag @throws cannot be grouped with parameter tags in a doc comment
Loading history...
108
     */
109
    protected function parseImage($value, $fieldInfo)
110
    {
111
        $upload = Hash::get($fieldInfo, 'options.upload');
112
        $conflict = Hash::get($fieldInfo, 'options.conflict');
113
114
        // Try to find an existing element
115
        $urlToUpload = null;
116
117
        // If we're uploading files, this will need to be an absolute URL. If it is, save until later.
118
        // We also don't check for existing assets here, so break out instantly.
119
        if ($upload && is_string($value) && UrlHelper::isAbsoluteUrl($value)) {
120
            $urlToUpload = $value;
121
122
            // If we're opting to use the already uploaded asset, we can check here
123
            if ($conflict === AssetElement::SCENARIO_INDEX) {
124
                $value = AssetHelper::getRemoteUrlFilename($value);
125
            }
126
        }
127
128
        // See if its a default asset
129
        if (is_array($value) && isset($value[0])) {
130
            return $value[0];
131
        }
132
133
        // Fetch all folders to search for an existing asset with the provided name
134
        $folderIds = (new Query())
135
            ->select(['id'])
136
            ->from([Table::VOLUMEFOLDERS])
137
            ->column();
138
139
        // Search anywhere in Craft
140
        $foundElement = AssetElement::find()
141
            ->filename($value)
142
            ->folderId($folderIds)
143
            ->one();
144
145
        // Do we want to match existing elements, and was one found?
146
        if ($foundElement && $conflict === AssetElement::SCENARIO_INDEX) {
147
            return [$foundElement->id];
148
        }
149
150
        // We can't find an existing asset, we need to download it, or plain ignore it
151
        if ($urlToUpload) {
152
            // Just get the first available folder. SEOMatic doesn't really support a nominated folder.
153
            $folderId = $folderIds[0];
154
155
            return AssetHelper::fetchRemoteImage([$urlToUpload], $fieldInfo, $this->feed, null, $this->element, $folderId);
156
        }
157
    }
158
}
159