deep-web-solutions/wordpress-framework-utilities

View on GitHub
src/includes/AdminNotices/AdminNoticesService.php

Summary

Maintainability
A
35 mins
Test Coverage
<?php

namespace DeepWebSolutions\Framework\Utilities\AdminNotices;

use DeepWebSolutions\Framework\Foundations\Actions\OutputtableInterface;
use DeepWebSolutions\Framework\Foundations\Logging\LoggingService;
use DeepWebSolutions\Framework\Foundations\PluginInterface;
use DeepWebSolutions\Framework\Foundations\Services\AbstractMultiHandlerService;
use DeepWebSolutions\Framework\Foundations\Services\Actions\OutputHandlersTrait;
use DeepWebSolutions\Framework\Foundations\Services\HandlerInterface;
use DeepWebSolutions\Framework\Foundations\Storage\StoreAwareInterface;
use DeepWebSolutions\Framework\Foundations\Storage\StoreInterface;
use DeepWebSolutions\Framework\Foundations\Storage\Stores\MemoryStore;
use DeepWebSolutions\Framework\Foundations\Storage\Stores\OptionsStore;
use DeepWebSolutions\Framework\Foundations\Storage\Stores\UserMetaStore;
use DeepWebSolutions\Framework\Utilities\AdminNotices\Handlers\DismissibleNoticesHandler;
use DeepWebSolutions\Framework\Utilities\AdminNotices\Handlers\SimpleNoticesHandler;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksService;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceAwareInterface;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceAwareTrait;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterInterface;
use DeepWebSolutions\Framework\Utilities\Hooks\HooksServiceRegisterTrait;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

\defined( 'ABSPATH' ) || exit;

/**
 * Compatibility layer between the framework and WordPress' API for admin notices.
 *
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 *
 * @since   1.0.0
 * @version 1.0.0
 * @author  Antonius Hegyes <a.hegyes@deep-web-solutions.com>
 * @package DeepWebSolutions\WP-Framework\Utilities\AdminNotices
 */
class AdminNoticesService extends AbstractMultiHandlerService implements HooksServiceAwareInterface, OutputtableInterface {
    // region TRAITS

    use HooksServiceAwareTrait;
    use HooksServiceRegisterTrait;
    use OutputHandlersTrait;

    // endregion

    // region MAGIC METHODS

    /**
     * AdminNoticesService constructor.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   PluginInterface                 $plugin             Instance of the plugin.
     * @param   LoggingService                  $logging_service    Instance of the logging service.
     * @param   HooksService                    $hooks_service      Instance of the hooks service.
     * @param   StoreInterface[]                $stores             Stores containing admin notices.
     * @param   AdminNoticesHandlerInterface[]  $handlers           Admin notices handlers to output.
     */
    public function __construct( PluginInterface $plugin, LoggingService $logging_service, HooksService $hooks_service, array $stores = array(), array $handlers = array() ) {
        $this->set_plugin( $plugin );
        $this->set_hooks_service( $hooks_service );

        $this->register_hooks( $hooks_service );

        $this->set_default_stores( $stores );
        parent::__construct( $plugin, $logging_service, $handlers );
    }

    // endregion

    // region INHERITED METHODS

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    public function register_handler( HandlerInterface $handler ): AdminNoticesService {
        parent::register_handler( $handler );

        if ( $handler instanceof HooksServiceRegisterInterface ) {
            $handler->register_hooks( $this->get_hooks_service() );
        }
        if ( $handler instanceof StoreAwareInterface ) {
            $handler->set_store( $this->get_store( 'admin-notices-stores' ) );
        }

        return $this;
    }

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    public function register_hooks( HooksService $hooks_service ): void {
        $hooks_service->add_action( 'admin_notices', $this, 'output' );
    }

    // endregion

    // region METHODS

    /**
     * Returns a given admin notices store.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $store_id   The ID of the admin notices store to retrieve.
     *
     * @return  StoreInterface
     */
    public function get_notices_store( string $store_id ): StoreInterface {
        return $this->get_store( 'admin-notices-stores' )->get( $store_id );
    }

    /**
     * Adds a notice notices to a given store.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   AdminNoticeInterface    $notice     Notice to add to the store.
     * @param   string                  $store_id   The ID of the store to add the notice to.
     *
     * @return  bool
     */
    public function add_notice( AdminNoticeInterface $notice, string $store_id = 'dynamic' ): bool {
        try {
            $result = $this->get_notices_store( $store_id )->add( $notice );
            return \is_null( $result ) || $result;
        } catch ( ContainerExceptionInterface $exception ) {
            return false;
        }
    }

    /**
     * Retrieves a notice from the given store.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $handle     Handle of the notice to retrieve.
     * @param   string  $store_id   The ID of the store to add the notice to.
     *
     * @return  AdminNoticeInterface|null
     */
    public function get_notice( string $handle, string $store_id = 'dynamic' ): ?AdminNoticeInterface {
        try {
            return $this->get_notices_store( $store_id )->get( $handle );
        } catch ( ContainerExceptionInterface $exception ) {
            return null;
        }
    }

    /**
     * Updates (or adds if it doesn't exist) a notice to the given store.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   AdminNoticeInterface    $notice     Notice to add to the store.
     * @param   string                  $store_id   The ID of the store to add the notice to.
     *
     * @return  bool
     */
    public function update_notice( AdminNoticeInterface $notice, string $store_id = 'dynamic' ): bool {
        try {
            $result = $this->get_notices_store( $store_id )->update( $notice );
            return \is_null( $result ) || $result;
        } catch ( ContainerExceptionInterface $exception ) {
            return false;
        }
    }

    /**
     * Removes a notice from a given store.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   string  $handle         Handle of the notice to remove.
     * @param   string  $store_id       The ID of the store to remove the notice from.
     *
     * @return  bool    Whether the operation was successful or not.
     */
    public function remove_notice( string $handle, string $store_id = 'dynamic' ): bool {
        try {
            $result = $this->get_notices_store( $store_id )->remove( $handle );
            return \is_null( $result ) || $result;
        } catch ( NotFoundExceptionInterface $exception ) {
            return true;
        } catch ( ContainerExceptionInterface $exception ) {
            return false;
        }
    }

    // endregion

    // region HELPERS

    /**
     * Register the stores passed on in the constructor together with the default stores.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @param   StoreInterface[]    $stores     Custom stores passed on through the constructor.
     */
    protected function set_default_stores( array $stores ): void {
        $database_key   = "_{$this->get_plugin()->get_plugin_safe_slug()}_admin_notices";
        $default_stores = array(
            new MemoryStore( 'dynamic' ),
            new OptionsStore( 'options', $database_key ),
            new UserMetaStore( 'user-meta', $database_key ),
        );

        $notices_stores_store = new MemoryStore( 'admin-notices-stores' );
        foreach ( \array_merge( $default_stores, $stores ) as $store ) {
            if ( $store instanceof StoreInterface ) {
                $notices_stores_store->update( $store );
            }
        }

        $this->register_store( $notices_stores_store );
    }

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    protected function get_default_handlers_classes(): array {
        return array( SimpleNoticesHandler::class, DismissibleNoticesHandler::class );
    }

    /**
     * {@inheritDoc}
     *
     * @since   1.0.0
     * @version 1.0.0
     */
    protected function get_handler_class(): string {
        return AdminNoticesHandlerInterface::class;
    }

    // endregion
}