Passed
Push — master ( 370def...949652 )
by Dominik
11:18 queued 07:17
created

Options::getTranslatable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 1
c 2
b 0
f 1
dl 0
loc 3
rs 10
cc 1
nc 1
nop 2
1
<?php
2
3
namespace Flynt\Utils;
4
5
use ACFComposer;
6
7
class Options
8
{
9
    const OPTION_TYPES = [
10
        'translatable' => [
11
            'title' => 'Translatable Options',
12
            'icon' => 'dashicons-translation',
13
            'translatable' => true
14
        ],
15
        'global' => [
16
            'title' => 'Global Options',
17
            'icon' => 'dashicons-admin-site',
18
            'translatable' => false
19
        ]
20
    ];
21
22
    const OPTION_CATEGORIES = [
23
        'component' => [
24
            'title' => 'Component',
25
            'icon' => 'dashicons-editor-table',
26
            'showType' => true
27
        ],
28
        'customPostType' => [
29
            'title' => 'Custom Post Type',
30
            'icon' => 'dashicons-palmtree',
31
            'showType' => true
32
            // 'label' => [ 'labels', 'menu_item' ], // TODO add this functionality
33
        ],
34
        'feature' => [
35
            'title' => 'Feature',
36
            'icon' => 'dashicons-carrot',
37
            'showType' => true
38
        ]
39
    ];
40
41
    protected static $initialized = false;
42
43
    protected static $optionPages = [];
44
45
    protected static $registeredOptions = [];
46
47
    protected static function createOptionPages()
48
    {
49
        if (static::$initialized) {
50
            return;
51
        } else {
52
            static::$initialized = true;
53
        }
54
        foreach (static::OPTION_TYPES as $optionType => $option) {
55
            $title = _x($option['title'], 'title', 'flynt');
56
            $slug = ucfirst($optionType) . 'Options';
57
58
            acf_add_options_page([
0 ignored issues
show
Bug introduced by
The function acf_add_options_page was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

58
            /** @scrutinizer ignore-call */ 
59
            acf_add_options_page([
Loading history...
59
                'page_title'  => $title,
60
                'menu_title'  => $title,
61
                'redirect'    => true,
62
                'menu_slug'   => $slug,
63
                'icon_url'    => $option['icon']
64
            ]);
65
66
            static::$optionPages[$optionType] = [
67
                'menu_slug' => $slug,
68
                'menu_title' => $title
69
            ];
70
            $fieldGroup = ACFComposer\ResolveConfig::forFieldGroup(
71
                [
72
                    'name' => $slug,
73
                    'title' => $title,
74
                    'style' => 'seamless',
75
                    'fields' => [],
76
                    'location' => [
77
                        [
78
                            [
79
                                'param' => 'options_page',
80
                                'operator' => '==',
81
                                'value' => $slug
82
                            ]
83
                        ]
84
                    ]
85
                ]
86
            );
87
            acf_add_local_field_group($fieldGroup);
0 ignored issues
show
Bug introduced by
The function acf_add_local_field_group was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

87
            /** @scrutinizer ignore-call */ 
88
            acf_add_local_field_group($fieldGroup);
Loading history...
88
        }
89
90
        add_action('current_screen', function ($currentScreen) {
91
            foreach (static::OPTION_TYPES as $optionType => $option) {
92
                $isTranslatable = $option['translatable'];
93
                $toplevelPageId = 'toplevel_page_' . $optionType;
94
                $menuTitle = static::$optionPages[$optionType]['menu_title'];
95
                $subPageId = sanitize_title($menuTitle) . '_page_' . $optionType;
96
                $currentScreenId = strtolower($currentScreen->id);
97
                $isCurrentPage = StringHelpers::startsWith(strtolower($toplevelPageId), $currentScreenId)
98
                || StringHelpers::startsWith(strtolower($subPageId), $currentScreenId);
99
100
                if (!$isTranslatable && $isCurrentPage) {
101
                    // set acf field values to default language
102
                    add_filter('acf/settings/current_language', 'Flynt\Utils\Options::getDefaultAcfLanguage', 101);
103
104
                    // hide language selector in admin bar
105
                    add_action('wp_before_admin_bar_render', function () {
106
                        $adminBar = $GLOBALS['wp_admin_bar'];
107
                        $adminBar->remove_menu('WPML_ALS');
108
                    });
109
                }
110
            }
111
        });
112
    }
113
114
115
    // ============
116
    // PUBLIC API
117
    // ============
118
    public static function getTranslatable($scope, $fieldName = null)
119
    {
120
        return self::get('translatable', $scope, $fieldName);
121
    }
122
123
    public static function getGlobal($scope, $fieldName = null)
124
    {
125
        return self::get('global', $scope, $fieldName);
126
    }
127
128
    /**
129
     * Get option(s) from a sub page.
130
     *
131
     * Returns an option of a sub page. If no field name is provided it will get all option of that sub page.
132
     * Parameters are expected to be camelCase.
133
     *
134
     * @since 0.2.0 introduced as a replacement for OptionPages::getOption and OptionPages::getOptions
135
     * @since 0.2.2 added check for required hooks to have run to alert of timing issues when used incorrectly
136
     *
137
     * @param string $optionType Type of option page. Either global or translatable.
138
     * @param string $optionCategory Category of option page. One of these three values: component, feature, customPostType.
139
     * @param string $subPageName Name of the sub page.
140
     * @param string $fieldName (optional) Name of the field to get.
141
     * @return mixed The value of the option or array of options. False if subpage doesn't exist or no option was found.
142
     **/
143
    public static function get($optionType, $scope, $fieldName = null)
144
    {
145
        if (!static::checkRequiredHooks($optionType, $scope, $fieldName)) {
146
            return false;
147
        }
148
149
        // convert parameters
150
        $optionType = lcfirst($optionType);
151
        $scope = ucfirst($scope);
152
153
        if (!isset(static::OPTION_TYPES[$optionType])) {
154
            return false;
155
        }
156
157
        $prefix = implode('_', [$optionType, $scope, '']);
158
        $isTranslatable = static::OPTION_TYPES[$optionType]['translatable'];
159
        if (empty($fieldName)) {
160
            $optionNames = ((static::$registeredOptions[$optionType] ?? [])[$scope] ?? []);
161
            return array_combine(
162
                $optionNames,
163
                array_map(function ($optionName) use ($prefix, $isTranslatable) {
164
                    $fieldKey = $prefix . $optionName;
165
                    return static::getOptionField($fieldKey, $isTranslatable);
166
                }, $optionNames)
167
            );
168
        } else {
169
            $fieldKey = $prefix . $fieldName;
170
            return static::getOptionField($fieldKey, $isTranslatable);
171
        }
172
    }
173
174
    public static function addTranslatable($scope, $fields, $category = null)
175
    {
176
        static::addOptions($scope, $fields, 'translatable', $category);
177
    }
178
179
    public static function addGlobal($scope, $fields, $category = null)
180
    {
181
        static::addOptions($scope, $fields, 'global', $category);
182
    }
183
184
    public static function addOptions($scope, $fields, $type, $category = null)
185
    {
186
        static::createOptionPages();
187
        if (empty($category)) {
188
            global $flyntCurrentOptionCategory;
189
            $category = $flyntCurrentOptionCategory ?? 'component';
190
        }
191
        $optionCategorySettings = static::OPTION_CATEGORIES[$category];
192
        $iconClasses = 'flynt-submenu-item dashicons-before ' . $optionCategorySettings['icon'];
193
        $prettyScope = StringHelpers::splitCamelCase($scope);
194
        $fieldGroupTitle = "<span class='{$iconClasses}'>{$prettyScope}</span>";
195
        $optionsPageSlug = self::$optionPages[$type]['menu_slug'];
196
        $fieldGroupName = implode('_', [$type, $scope]);
197
        static::addOptionsFieldGroup($fieldGroupName, $fieldGroupTitle, $optionsPageSlug, $fields);
198
        static::registerOptionNames($type, $scope, $fields);
199
    }
200
201
    protected static function registerOptionNames($type, $scope, $fields)
202
    {
203
        static::$registeredOptions[$type] = static::$registeredOptions[$type] ?? [];
204
        static::$registeredOptions[$type] = static::$registeredOptions[$type] ?? [];
205
        static::$registeredOptions[$type][$scope] = array_column($fields, 'name');
206
        return static::$registeredOptions;
207
    }
208
209
    protected static function addOptionsFieldGroup($name, $title, $optionsPageSlug, $fields)
210
    {
211
        $fieldGroup = ACFComposer\ResolveConfig::forFieldGroup(
212
            [
213
                'name' => $name,
214
                'title' => $title,
215
                'fields' => array_merge([
216
                    [
217
                        'label' => $title,
218
                        'name' => '',
219
                        'type' => 'accordion',
220
                        'placement' => 'left',
221
                        'endpoint' => false,
222
                    ]
223
                ], $fields),
224
                'style' => 'seamless',
225
                'location' => [
226
                    [
227
                        [
228
                            'param' => 'options_page',
229
                            'operator' => '==',
230
                            'value' => $optionsPageSlug
231
                        ]
232
                    ]
233
                ]
234
            ]
235
        );
236
        $fieldGroup['fields'] = static::prefixFields($fieldGroup['fields'], $name);
237
        foreach ($fieldGroup['fields'] as $field) {
238
            acf_add_local_field(array_merge($field, [
0 ignored issues
show
Bug introduced by
The function acf_add_local_field was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

238
            /** @scrutinizer ignore-call */ 
239
            acf_add_local_field(array_merge($field, [
Loading history...
239
                'parent' => 'group_' . $optionsPageSlug,
240
            ]));
241
        }
242
    }
243
244
    protected static function prefixFields($fields, $prefix)
245
    {
246
        return array_map(function ($field) use ($prefix) {
247
            $field['name'] = $prefix . '_' . $field['name'];
248
            return $field;
249
        }, $fields);
250
    }
251
252
    protected static function checkRequiredHooks($optionType, $scope, $fieldName)
253
    {
254
        if (did_action('acf/init') < 1) {
255
            $parameters = "${optionType}, ${scope}, ";
256
            $parameters .= isset($fieldName) ? $fieldName : 'NULL';
257
            trigger_error("Could not get option/s for [${parameters}]. Required hooks have not yet been executed! Please make sure to run `Options::get()` after the `acf/init` action is finished.", E_USER_WARNING);
258
            return false;
259
        }
260
        return true;
261
    }
262
263
    protected static function getOptionField($key, $translatable)
264
    {
265
        if ($translatable) {
266
            $option = get_field('field_' . $key, 'option');
0 ignored issues
show
Bug introduced by
The function get_field was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

266
            $option = /** @scrutinizer ignore-call */ get_field('field_' . $key, 'option');
Loading history...
267
        } else {
268
            // switch to default language to get global options
269
            add_filter('acf/settings/current_language', 'Flynt\Utils\Options::getDefaultAcfLanguage', 100);
270
271
            $option = get_field('field_' . $key, 'option');
272
273
            remove_filter('acf/settings/current_language', 'Flynt\Utils\Options::getDefaultAcfLanguage', 100);
274
        }
275
276
        return $option;
277
    }
278
279
    public static function getDefaultAcfLanguage()
280
    {
281
        return acf_get_setting('default_language');
0 ignored issues
show
Bug introduced by
The function acf_get_setting was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

281
        return /** @scrutinizer ignore-call */ acf_get_setting('default_language');
Loading history...
282
    }
283
}
284