flyntwp /
flynt
| 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 | protected static $initialized = false; |
||||||
| 23 | |||||||
| 24 | protected static $optionPages = []; |
||||||
| 25 | |||||||
| 26 | protected static $registeredOptions = []; |
||||||
| 27 | |||||||
| 28 | protected static function init() |
||||||
| 29 | { |
||||||
| 30 | if (static::$initialized) { |
||||||
| 31 | return; |
||||||
| 32 | } else { |
||||||
| 33 | static::$initialized = true; |
||||||
| 34 | } |
||||||
| 35 | |||||||
| 36 | add_action('current_screen', function ($currentScreen) { |
||||||
| 37 | $currentScreenId = strtolower($currentScreen->id); |
||||||
| 38 | foreach (static::OPTION_TYPES as $optionType => $option) { |
||||||
| 39 | $isTranslatable = $option['translatable']; |
||||||
| 40 | // NOTE: because the first subpage starts with toplevel instead (there is no overview page) |
||||||
| 41 | $toplevelPageId = strtolower('toplevel_page_' . $optionType); |
||||||
| 42 | $menuTitle = static::$optionPages[$optionType]['menu_title']; |
||||||
| 43 | // NOTE: all other subpages have the parent menu-title in front instead |
||||||
| 44 | $subPageId = strtolower( |
||||||
| 45 | sanitize_title($menuTitle) . '_page_' . $optionType |
||||||
| 46 | ); |
||||||
| 47 | $isCurrentPage = |
||||||
| 48 | StringHelpers::startsWith( |
||||||
| 49 | $toplevelPageId, |
||||||
| 50 | $currentScreenId |
||||||
| 51 | ) || |
||||||
| 52 | StringHelpers::startsWith($subPageId, $currentScreenId); |
||||||
| 53 | if (!$isTranslatable && $isCurrentPage) { |
||||||
| 54 | // set acf field values to default language |
||||||
| 55 | add_filter( |
||||||
| 56 | 'acf/settings/current_language', |
||||||
| 57 | 'Flynt\Utils\Options::getDefaultAcfLanguage', |
||||||
| 58 | 101 |
||||||
| 59 | ); |
||||||
| 60 | // hide language selector in admin bar |
||||||
| 61 | add_action('wp_before_admin_bar_render', function () { |
||||||
| 62 | $adminBar = $GLOBALS['wp_admin_bar']; |
||||||
| 63 | $adminBar->remove_menu('WPML_ALS'); |
||||||
| 64 | }); |
||||||
| 65 | } |
||||||
| 66 | } |
||||||
| 67 | }); |
||||||
| 68 | } |
||||||
| 69 | |||||||
| 70 | protected static function createOptionPage($optionType) |
||||||
| 71 | { |
||||||
| 72 | if (empty(static::$optionPages[$optionType])) { |
||||||
| 73 | $option = static::OPTION_TYPES[$optionType]; |
||||||
| 74 | $title = _x($option['title'], 'title', 'flynt'); |
||||||
| 75 | $slug = ucfirst($optionType) . 'Options'; |
||||||
| 76 | |||||||
| 77 | acf_add_options_page([ |
||||||
|
0 ignored issues
–
show
Bug
introduced
by
Loading history...
|
|||||||
| 78 | 'page_title' => $title, |
||||||
| 79 | 'menu_title' => $title, |
||||||
| 80 | 'redirect' => true, |
||||||
| 81 | 'menu_slug' => $slug, |
||||||
| 82 | 'icon_url' => $option['icon'] |
||||||
| 83 | ]); |
||||||
| 84 | |||||||
| 85 | static::$optionPages[$optionType] = [ |
||||||
| 86 | 'menu_slug' => $slug, |
||||||
| 87 | 'menu_title' => $title |
||||||
| 88 | ]; |
||||||
| 89 | } |
||||||
| 90 | return static::$optionPages[$optionType]; |
||||||
| 91 | } |
||||||
| 92 | |||||||
| 93 | protected static function createOptionSubPage($optionType, $optionCategory = "Default") |
||||||
| 94 | { |
||||||
| 95 | if (empty(static::$optionPages[$optionType]['sub_pages'][$optionCategory])) { |
||||||
| 96 | $optionPage = static::createOptionPage($optionType); |
||||||
| 97 | $categoryTitle = _x($optionCategory, 'title', 'flynt'); |
||||||
| 98 | $categorySlug = implode('-', [$optionPage['menu_slug'], $optionCategory]); |
||||||
| 99 | $pageConfig = [ |
||||||
| 100 | 'page_title' => $optionPage['menu_title'] . ': ' . $categoryTitle, |
||||||
| 101 | 'menu_title' => $categoryTitle, |
||||||
| 102 | 'redirect' => true, |
||||||
| 103 | 'menu_slug' => $categorySlug, |
||||||
| 104 | 'parent_slug' => $optionPage['menu_slug'] |
||||||
| 105 | ]; |
||||||
| 106 | acf_add_options_page($pageConfig); |
||||||
|
0 ignored issues
–
show
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
Loading history...
|
|||||||
| 107 | static::$optionPages[$optionType]['sub_pages'][ |
||||||
| 108 | $optionCategory |
||||||
| 109 | ] = [ |
||||||
| 110 | 'menu_slug' => $categorySlug, |
||||||
| 111 | 'menu_title' => $categoryTitle |
||||||
| 112 | ]; |
||||||
| 113 | $fieldGroup = ACFComposer\ResolveConfig::forFieldGroup([ |
||||||
| 114 | 'name' => $categorySlug, |
||||||
| 115 | 'title' => $categoryTitle, |
||||||
| 116 | 'style' => 'seamless', |
||||||
| 117 | 'fields' => [], |
||||||
| 118 | 'location' => [ |
||||||
| 119 | [ |
||||||
| 120 | [ |
||||||
| 121 | 'param' => 'options_page', |
||||||
| 122 | 'operator' => '==', |
||||||
| 123 | 'value' => $categorySlug |
||||||
| 124 | ] |
||||||
| 125 | ] |
||||||
| 126 | ] |
||||||
| 127 | ]); |
||||||
| 128 | acf_add_local_field_group($fieldGroup); |
||||||
|
0 ignored issues
–
show
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
Loading history...
|
|||||||
| 129 | } |
||||||
| 130 | } |
||||||
| 131 | |||||||
| 132 | |||||||
| 133 | // ============ |
||||||
| 134 | // PUBLIC API |
||||||
| 135 | // ============ |
||||||
| 136 | public static function getTranslatable($scope, $fieldName = null) |
||||||
| 137 | { |
||||||
| 138 | return self::get('translatable', $scope, $fieldName); |
||||||
| 139 | } |
||||||
| 140 | |||||||
| 141 | public static function getGlobal($scope, $fieldName = null) |
||||||
| 142 | { |
||||||
| 143 | return self::get('global', $scope, $fieldName); |
||||||
| 144 | } |
||||||
| 145 | |||||||
| 146 | /** |
||||||
| 147 | * Get option(s) from a sub page. |
||||||
| 148 | * |
||||||
| 149 | * Returns an option of a sub page. If no field name is provided it will get all option of that sub page. |
||||||
| 150 | * Parameters are expected to be camelCase. |
||||||
| 151 | * |
||||||
| 152 | * @since 0.2.0 introduced as a replacement for OptionPages::getOption and OptionPages::getOptions |
||||||
| 153 | * @since 0.2.2 added check for required hooks to have run to alert of timing issues when used incorrectly |
||||||
| 154 | * |
||||||
| 155 | * @param string $optionType Type of option page. Either global or translatable. |
||||||
| 156 | * @param string $scope Scope of the option. |
||||||
| 157 | * @param string|null $fieldName (optional) Name of the field to get. |
||||||
| 158 | * @return mixed The value of the option or array of options. False if subpage doesn't exist or no option was found. |
||||||
| 159 | **/ |
||||||
| 160 | public static function get($optionType, $scope, $fieldName = null) |
||||||
| 161 | { |
||||||
| 162 | if (!static::checkRequiredHooks($optionType, $scope, $fieldName)) { |
||||||
| 163 | return false; |
||||||
| 164 | } |
||||||
| 165 | |||||||
| 166 | // convert parameters |
||||||
| 167 | $optionType = lcfirst($optionType); |
||||||
| 168 | $scope = ucfirst($scope); |
||||||
| 169 | |||||||
| 170 | if (!isset(static::OPTION_TYPES[$optionType])) { |
||||||
| 171 | return false; |
||||||
| 172 | } |
||||||
| 173 | |||||||
| 174 | $prefix = implode('_', [$optionType, $scope, '']); |
||||||
| 175 | $isTranslatable = static::OPTION_TYPES[$optionType]['translatable']; |
||||||
| 176 | if (empty($fieldName)) { |
||||||
| 177 | $optionNames = ((static::$registeredOptions[$optionType] ?? [])[$scope] ?? []); |
||||||
| 178 | return array_combine( |
||||||
| 179 | $optionNames, |
||||||
| 180 | array_map(function ($optionName) use ($prefix, $isTranslatable) { |
||||||
| 181 | $fieldKey = $prefix . $optionName; |
||||||
| 182 | return static::getOptionField($fieldKey, $isTranslatable); |
||||||
| 183 | }, $optionNames) |
||||||
| 184 | ); |
||||||
| 185 | } else { |
||||||
| 186 | $fieldKey = $prefix . $fieldName; |
||||||
| 187 | return static::getOptionField($fieldKey, $isTranslatable); |
||||||
| 188 | } |
||||||
| 189 | } |
||||||
| 190 | |||||||
| 191 | public static function addTranslatable($scope, $fields, $category = 'Default') |
||||||
| 192 | { |
||||||
| 193 | static::addOptions($scope, $fields, 'translatable', $category); |
||||||
| 194 | } |
||||||
| 195 | |||||||
| 196 | public static function addGlobal($scope, $fields, $category = 'Default') |
||||||
| 197 | { |
||||||
| 198 | static::addOptions($scope, $fields, 'global', $category); |
||||||
| 199 | } |
||||||
| 200 | |||||||
| 201 | public static function addOptions($scope, $fields, $type, $category = 'Default') |
||||||
| 202 | { |
||||||
| 203 | static::createOptionSubPage($type, $category); |
||||||
| 204 | $fieldGroupTitle = StringHelpers::splitCamelCase($scope); |
||||||
| 205 | $optionsPageSlug = self::$optionPages[$type]['sub_pages'][$category]['menu_slug']; |
||||||
| 206 | $fieldGroupName = implode('_', [$type, $scope]); |
||||||
| 207 | static::addOptionsFieldGroup( |
||||||
| 208 | $fieldGroupName, |
||||||
| 209 | $fieldGroupTitle, |
||||||
| 210 | $optionsPageSlug, |
||||||
| 211 | $fields |
||||||
| 212 | ); |
||||||
| 213 | static::registerOptionNames($type, $scope, $fields); |
||||||
| 214 | } |
||||||
| 215 | |||||||
| 216 | protected static function registerOptionNames($type, $scope, $fields) |
||||||
| 217 | { |
||||||
| 218 | static::$registeredOptions[$type] = static::$registeredOptions[$type] ?? []; |
||||||
| 219 | static::$registeredOptions[$type] = static::$registeredOptions[$type] ?? []; |
||||||
| 220 | static::$registeredOptions[$type][$scope] = array_column($fields, 'name'); |
||||||
| 221 | return static::$registeredOptions; |
||||||
| 222 | } |
||||||
| 223 | |||||||
| 224 | protected static function addOptionsFieldGroup($name, $title, $optionsPageSlug, $fields) |
||||||
| 225 | { |
||||||
| 226 | $fieldGroup = ACFComposer\ResolveConfig::forFieldGroup( |
||||||
| 227 | [ |
||||||
| 228 | 'name' => $name, |
||||||
| 229 | 'title' => $title, |
||||||
| 230 | 'fields' => array_merge([ |
||||||
| 231 | [ |
||||||
| 232 | 'label' => $title, |
||||||
| 233 | 'name' => '', |
||||||
| 234 | 'type' => 'accordion', |
||||||
| 235 | 'placement' => 'left', |
||||||
| 236 | 'endpoint' => false, |
||||||
| 237 | ] |
||||||
| 238 | ], $fields), |
||||||
| 239 | 'style' => 'seamless', |
||||||
| 240 | 'location' => [ |
||||||
| 241 | [ |
||||||
| 242 | [ |
||||||
| 243 | 'param' => 'options_page', |
||||||
| 244 | 'operator' => '==', |
||||||
| 245 | 'value' => $optionsPageSlug |
||||||
| 246 | ] |
||||||
| 247 | ] |
||||||
| 248 | ] |
||||||
| 249 | ] |
||||||
| 250 | ); |
||||||
| 251 | $fieldGroup['fields'] = static::prefixFields($fieldGroup['fields'], $name); |
||||||
| 252 | foreach ($fieldGroup['fields'] as $field) { |
||||||
| 253 | acf_add_local_field(array_merge($field, [ |
||||||
|
0 ignored issues
–
show
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
Loading history...
|
|||||||
| 254 | 'parent' => 'group_' . $optionsPageSlug, |
||||||
| 255 | ])); |
||||||
| 256 | } |
||||||
| 257 | } |
||||||
| 258 | |||||||
| 259 | protected static function prefixFields($fields, $prefix) |
||||||
| 260 | { |
||||||
| 261 | return array_map(function ($field) use ($prefix) { |
||||||
| 262 | $field['name'] = $prefix . '_' . $field['name']; |
||||||
| 263 | return $field; |
||||||
| 264 | }, $fields); |
||||||
| 265 | } |
||||||
| 266 | |||||||
| 267 | protected static function checkRequiredHooks($optionType, $scope, $fieldName) |
||||||
| 268 | { |
||||||
| 269 | if (did_action('acf/init') < 1) { |
||||||
| 270 | $parameters = "${optionType}, ${scope}, "; |
||||||
| 271 | $parameters .= isset($fieldName) ? $fieldName : 'NULL'; |
||||||
| 272 | 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); |
||||||
| 273 | return false; |
||||||
| 274 | } |
||||||
| 275 | return true; |
||||||
| 276 | } |
||||||
| 277 | |||||||
| 278 | protected static function getOptionField($key, $translatable) |
||||||
| 279 | { |
||||||
| 280 | if ($translatable) { |
||||||
| 281 | $option = get_field('field_' . $key, 'option'); |
||||||
|
0 ignored issues
–
show
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
Loading history...
|
|||||||
| 282 | } else { |
||||||
| 283 | // switch to default language to get global options |
||||||
| 284 | add_filter('acf/settings/current_language', 'Flynt\Utils\Options::getDefaultAcfLanguage', 100); |
||||||
| 285 | |||||||
| 286 | $option = get_field('field_' . $key, 'option'); |
||||||
| 287 | |||||||
| 288 | remove_filter('acf/settings/current_language', 'Flynt\Utils\Options::getDefaultAcfLanguage', 100); |
||||||
| 289 | } |
||||||
| 290 | |||||||
| 291 | return $option; |
||||||
| 292 | } |
||||||
| 293 | |||||||
| 294 | public static function getDefaultAcfLanguage() |
||||||
| 295 | { |
||||||
| 296 | return acf_get_setting('default_language'); |
||||||
|
0 ignored issues
–
show
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
Loading history...
|
|||||||
| 297 | } |
||||||
| 298 | } |
||||||
| 299 |