*/ protected array $values; protected SettingsData $settingsData; protected Settings $settings; protected ViewsDataStorage $viewsDataStorage; protected CardsDataStorage $cardsDataStorage; protected string $savedMessage; public function __construct( SettingsData $settingsData, Settings $settings, ViewsDataStorage $viewsDataStorage, CardsDataStorage $cardsDataStorage ) { $this->values = []; $this->settingsData = $settingsData; $this->settings = $settings; $this->viewsDataStorage = $viewsDataStorage; $this->cardsDataStorage = $cardsDataStorage; $this->savedMessage = ''; } /** * @param mixed $postId */ protected function isMySource($postId): bool { $screen = get_current_screen(); return null !== $screen && 'acf_views_page_acf-views-settings' === $screen->id && 'options' === $postId; } protected function activateFsStorage(): void { if (false === mkdir($this->viewsDataStorage->getFileSystem()->getTargetBaseFolder(), 0755)) { $this->savedMessage = __( 'Fail to activate the file system storage. Check your FS permissions.', 'acf-views' ); return; } // set, as the folder was just created $this->viewsDataStorage->getFileSystem()->setBaseFolder(); $this->cardsDataStorage->getFileSystem()->setBaseFolder(); $this->viewsDataStorage->activateFileSystemStorage(); $this->cardsDataStorage->activateFileSystemStorage(); } protected function deactivateFsStorage(): void { $themeTemplatesFolder = $this->viewsDataStorage->getFileSystem()->getBaseFolder(); $this->viewsDataStorage->deactivateFileSystemStorage(); $this->cardsDataStorage->deactivateFileSystemStorage(); $isRemoved = $this->viewsDataStorage->getFileSystem()->removeFolderRecursively($themeTemplatesFolder); if (true === $isRemoved) { return; } $this->savedMessage = __( 'Fail to deactivate the file system storage. Check your FS permissions.', 'acf-views' ); } public function addPage(): void { // do not use 'acf_add_options_page', as the global options-related functions may be unavailable // (in case of the manual include) if (!function_exists('acf_options_page')) { return; } $resultMessage = sanitize_text_field($_GET['resultMessage'] ?? ''); $updatedMessage = '' === $resultMessage ? __('Settings successfully updated.', 'acf-views') : $resultMessage; acf_options_page()->add_page([ 'slug' => self::SLUG, 'page_title' => __('Settings', 'acf-views'), 'menu_title' => __('Settings', 'acf-views'), 'parent_slug' => sprintf('edit.php?post_type=%s', ViewsCpt::NAME), 'position' => 2, 'update_button' => __('Save changes', 'acf-views'), 'updated_message' => $updatedMessage, ]); } /** * @param mixed $postId */ public function maybeCatchValues($postId): void { if (!$this->isMySource($postId)) { return; } add_filter('acf/pre_update_value', function ($isUpdated, $value, $postId, array $field): bool { // extra check, as probably it's about another post if (!$this->isMySource($postId)) { return $isUpdated; } $fieldName = (string)($field['name'] ?? ''); $this->values[$fieldName] = $value; // avoid saving to the postmeta return true; }, 10, 4); } public function maybeInjectValues(): void { if (!$this->isMySource('options')) { return; } add_filter('acf/pre_load_value', function ($value, $postId, $field) { // extra check, as probably it's about another post if (!$this->isMySource($postId)) { return $value; } $fieldName = $field['name']; $value = ''; switch ($fieldName) { case SettingsData::getAcfFieldName(SettingsData::FIELD_IS_DEV_MODE): $value = $this->settings->isDevMode(); break; case SettingsData::getAcfFieldName(SettingsData::FIELD_IS_FILE_SYSTEM_STORAGE): $value = '' !== $this->viewsDataStorage->getFileSystem()->getBaseFolder(); break; } return $value; }, 10, 3); } /** * @param mixed $postId * @throws Exception */ public function maybeProcess($postId): void { if (!$this->isMySource($postId) || [] === $this->values) { return; } $this->settingsData->load(false, '', $this->values); $this->settings->setIsDevMode($this->settingsData->isDevMode); if (true === $this->settingsData->isFileSystemStorage && false === $this->viewsDataStorage->getFileSystem()->isActive()) { $this->activateFsStorage(); } if (false === $this->settingsData->isFileSystemStorage && true === $this->viewsDataStorage->getFileSystem()->isActive()) { $this->deactivateFsStorage(); } $this->settings->save(); if ('' === $this->savedMessage) { return; } wp_redirect(add_query_arg([ 'message' => 1, 'resultMessage' => $this->savedMessage, ])); exit; } public function setHooks(CurrentScreen $currentScreen): void { if (false === $currentScreen->isAdmin()) { return; } // init, not acf/init, as the method uses 'get_edit_post_link' which will be available only since this hook // (because we sign up the CPTs in this hook) add_action('init', [$this, 'addPage',]); add_action('acf/save_post', [$this, 'maybeCatchValues',]); // priority 20, as it's after the ACF's save_post hook add_action('acf/save_post', [$this, 'maybeProcess',], 20); add_action('acf/input/admin_head', [$this, 'maybeInjectValues']); } }