Passed
Push — master ( b0b3b0...3d5da5 )
by M. Mikkel
04:21
created

CpFieldInspect   A

Complexity

Total Complexity 22

Size/Duplication

Total Lines 187
Duplicated Lines 0 %

Importance

Changes 11
Bugs 0 Features 0
Metric Value
eloc 79
c 11
b 0
f 0
dl 0
loc 187
rs 10
wmc 22

3 Methods

Rating   Name   Duplication   Size   Complexity  
A init() 0 33 4
B doIt() 0 84 11
B renderEditSourceLink() 0 22 7
1
<?php
2
/**
3
 * CP Field Inspect plugin for Craft CMS 3.x
4
 *
5
 * Inspect field handles and easily edit field settings
6
 *
7
 * @link      http://mmikkel.no
8
 * @copyright Copyright (c) 2017 Mats Mikkel Rummelhoff
9
 */
10
11
namespace mmikkel\cpfieldinspect;
12
13
use Craft;
14
use craft\base\Element;
15
use craft\base\ElementInterface;
16
use craft\base\Plugin;
17
use craft\commerce\elements\Product;
18
use craft\elements\Asset;
19
use craft\elements\Category;
20
use craft\elements\Entry;
21
use craft\elements\GlobalSet;
22
use craft\elements\User;
23
use craft\events\DefineHtmlEvent;
24
use craft\events\PluginEvent;
25
use craft\helpers\UrlHelper;
26
use craft\services\Plugins;
27
28
use yii\base\Event;
29
30
/**
31
 * Craft plugins are very much like little applications in and of themselves. We’ve made
32
 * it as simple as we can, but the training wheels are off. A little prior knowledge is
33
 * going to be required to write a plugin.
34
 *
35
 * For the purposes of the plugin docs, we’re going to assume that you know PHP and SQL,
36
 * as well as some semi-advanced concepts like object-oriented programming and PHP namespaces.
37
 *
38
 * https://craftcms.com/docs/plugins/introduction
39
 *
40
 * @author    Mats Mikkel Rummelhoff
41
 * @package   CpFieldInspect
42
 * @since     1.0.0
43
 *
44
 *
45
 * Plugin icon credit: CUSTOMIZE SEARCH by creative outlet from the Noun Project
46
 *
47
 */
48
49
/**
50
 * Class CpFieldInspect
51
 * @package mmikkel\cpfieldinspect
52
 *
53
 */
54
class CpFieldInspect extends Plugin
55
{
56
    // Static Properties
57
    // =========================================================================
58
59
    /**
60
     * Static property that is an instance of this plugin class so that it can be accessed via
61
     * CpFieldInspect::$plugin
62
     *
63
     * @var CpFieldInspect
64
     */
65
    public static $plugin;
66
67
    // Public Methods
68
    // =========================================================================
69
70
    /**
71
     * Set our $plugin static property to this class so that it can be accessed via
72
     * CpFieldInspect::$plugin
73
     *
74
     * Called after the plugin class is instantiated; do any one-time initialization
75
     * here such as hooks and events.
76
     *
77
     * If you have a '/vendor/autoload.php' file, it will be loaded for you automatically;
78
     * you do not need to load it in your init() method.
79
     *
80
     */
81
    public function init()
82
    {
83
        parent::init();
84
        self::$plugin = $this;
85
86
        $config = Craft::$app->getConfig()->getGeneral();
87
        if (!$config->allowAdminChanges) {
88
            // Do nothing if admin changes aren't allowed
89
            return;
90
        }
91
92
        $request = Craft::$app->getRequest();
93
        if (!$request->getIsCpRequest() || $request->getIsConsoleRequest()) {
94
            // Also do nothing if this is a console or site request
95
            return;
96
        }
97
98
        // Handler: EVENT_AFTER_LOAD_PLUGINS
99
        Event::on(
100
            Plugins::class,
101
            Plugins::EVENT_AFTER_LOAD_PLUGINS,
102
            function () {
103
                $this->doIt();
104
            }
105
        );
106
107
        Craft::info(
108
            Craft::t(
109
                'cp-field-inspect',
110
                '{name} plugin loaded',
111
                ['name' => $this->name]
112
            ),
113
            __METHOD__
114
        );
115
    }
116
117
    // Protected Methods
118
    // =========================================================================
119
120
    /**
121
     * @throws \yii\base\Exception
122
     * @throws \yii\base\InvalidConfigException
123
     */
124
    protected function doIt()
125
    {
126
127
        if (!Craft::$app->getUser()->getIsAdmin()) {
128
            // Do nothing if the user is not an admin
129
            return;
130
        }
131
132
        /** @var User $user */
133
        $user = Craft::$app->getUser()->getIdentity();
134
        if (!$user->getPreference('showFieldHandles')) {
135
            // Do nothing if the user is not an admin, or if field handles aren't visible
136
            return;
137
        }
138
139
        // Render edit source links
140
        if (\version_compare(Craft::$app->getVersion(), '4.0', '<')) {
141
142
            // Legacy template hooks for entries, assets and categories on Craft 3.x
143
            Craft::$app->getView()->hook('cp.entries.edit.meta', function (array $context) {
144
                return $this->renderEditSourceLink($context);
145
            });
146
            Craft::$app->getView()->hook('cp.assets.edit.meta', function (array $context) {
147
                return $this->renderEditSourceLink($context);
148
            });
149
            Craft::$app->getView()->hook('cp.categories.edit.details', function (array $context) {
150
                return $this->renderEditSourceLink($context);
151
            });
152
153
        } else {
154
155
            // Use the EVENT_DEFINE_META_FIELDS_HTML event to inject source buttons for Craft 4
156
            Event::on(
157
                Element::class,
158
                Element::EVENT_DEFINE_META_FIELDS_HTML,
159
                function (DefineHtmlEvent $event) {
160
                    if ($event->static) {
161
                        return;
162
                    }
163
                    $event->html .= $this->renderEditSourceLink(['element' => $event->sender]);
164
                }
165
            );
166
        }
167
168
        // Hooks that work on Craft 3.x and 4.x
169
        Craft::$app->getView()->hook('cp.globals.edit.content', function (array $context) {
170
            return $this->renderEditSourceLink($context);
171
        });
172
        Craft::$app->getView()->hook('cp.users.edit.details', function (array $context) {
173
            return $this->renderEditSourceLink($context);
174
        });
175
        Craft::$app->getView()->hook('cp.commerce.product.edit.details', function (array $context) {
176
            return $this->renderEditSourceLink($context);
177
        });
178
179
        $request = Craft::$app->getRequest();
180
        $isAjax = $request->getIsAjax() || $request->getAcceptsJson();
181
182
        if ($isAjax) {
183
184
            $segments = $request->getActionSegments();
185
            if (empty($segments) || !\is_array($segments) || $segments[count($segments) - 1] !== 'get-editor-html') {
186
                return;
187
            }
188
189
            Craft::$app->getView()->registerJs('Craft.CpFieldInspectPlugin.initElementEditor();');
190
191
        } else {
192
193
            $redirectUrl = \implode('?', \array_filter([\implode('/', $request->getSegments()), $request->getQueryStringWithoutPath()]));
194
195
            $data = [
196
                'editFieldBtnLabel' => Craft::t('cp-field-inspect', 'Edit field settings'),
197
                'baseEditFieldUrl' => \rtrim(UrlHelper::cpUrl('settings/fields/edit'), '/'),
198
                'redirectUrl' => Craft::$app->getSecurity()->hashData($redirectUrl, Craft::$app->getConfig()->getGeneral()->securityKey),
199
            ];
200
201
            $fields = Craft::$app->getFields()->getAllFields('global');
202
            foreach ($fields as $field) {
203
                $data['fields'][$field->handle] = (int)$field->id;
204
            }
205
206
            Craft::$app->getView()->registerAssetBundle(CpFieldInspectBundle::class);
207
            Craft::$app->getView()->registerJs('Craft.CpFieldInspectPlugin.init(' . \json_encode($data) . ');');
208
        }
209
    }
210
211
    /**
212
     * @return string
213
     * @throws \Twig\Error\LoaderError
214
     * @throws \Twig\Error\RuntimeError
215
     * @throws \Twig\Error\SyntaxError
216
     * @throws \Twig\Error\LoaderError
217
     * @throws \yii\base\Exception
218
     */
219
    protected function renderEditSourceLink(array $context): string
220
    {
221
        $element = $context['element'] ?? $context['entry'] ?? $context['asset'] ?? $context['globalSet'] ?? $context['user'] ?? $context['category'] ?? $context['product'] ?? null;
222
        if ($element instanceof Entry) {
223
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-entry-type-link', ['entry' => $element]);
224
        }
225
        if ($element instanceof Asset) {
226
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-volume-link', ['asset' => $element]);
227
        }
228
        if ($element instanceof GlobalSet) {
229
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-globalset-link', ['globalSet' => $element]);
230
        }
231
        if ($element instanceof User) {
232
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-users-link', ['user' => $element]);
233
        }
234
        if ($element instanceof Category) {
235
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-category-group-link', ['category' => $element]);
236
        }
237
        if ($element instanceof Product) {
238
            return Craft::$app->getView()->renderTemplate('cp-field-inspect/edit-commerce-product-type-link', ['product' => $element]);
239
        }
240
        return '';
241
    }
242
243
}
244