deep-web-solutions/wordpress-framework-core

View on GitHub
src/includes/Functionalities/AbstractPermissionsChildFunctionality.php

Summary

Maintainability
C
1 day
Test Coverage
<?php

namespace DeepWebSolutions\Framework\Core\Functionalities;

use DeepWebSolutions\Framework\Core\AbstractPluginFunctionality;
use DeepWebSolutions\Framework\Foundations\Exceptions\NotFoundException;
use DeepWebSolutions\Framework\Utilities\Caching\Actions\InitializeCachingServiceTrait;
use DeepWebSolutions\Framework\Utilities\Caching\CachingServiceAwareInterface;

\defined( 'ABSPATH' ) || exit;

/**
 * Standardizes the splitting of permissions across multiple files.
 *
 * @since   1.0.0
 * @version 1.0.0
 * @author  Antonius Hegyes <a.hegyes@deep-web-solutions.com>
 * @package DeepWebSolutions\WP-Framework\Core\Functionalities
 */
abstract class AbstractPermissionsChildFunctionality extends AbstractPluginFunctionality implements CachingServiceAwareInterface {
    // region TRAITS

    use InitializeCachingServiceTrait;

    // endregion

    // region METHODS

    /**
     * Returns a list of the current instance's permissions. By default that's all the public constants of the class
     * but inheriting classes can override this to provide a different logic.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @return  array
     */
    public function get_permissions(): array {
        return self::get_reflection_class()->getConstants();
    }

    /**
     * Returns a list of the current instance's permission constants + a list of all children's recursive permission constants.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @return  string[]
     */
    final public function collect_permissions(): array {
        $permissions_key = "permissions_{$this->get_id()}";
        $permissions     = $this->get_cache_value( $permissions_key );

        if ( $permissions instanceof NotFoundException ) {
            $permissions = $this->get_permissions();
            foreach ( $this->get_children() as $child ) {
                if ( \is_a( $child, self::class ) ) {
                    $permissions += $child->collect_permissions();
                }
            }

            $this->set_cache_value( $permissions_key, $permissions );
        }

        return $permissions;
    }

    /**
     * Returns a definition array of how to grant this instance's permissions during the installation routine.
     * Inheriting classes can overwrite this to change the default logic.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @return  array
     */
    public function get_granting_rules(): array {
        return array( 'administrator' => 'all' );
    }

    /**
     * Returns a list of which roles each permission should be granted to for the current instance + all the instance's permissions children.
     *
     * @since   1.0.0
     * @version 1.0.0
     *
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     *
     * @return  array
     */
    final public function collect_granting_rules(): array {
        $rules_key = "permissions_rules_{$this->get_id()}";
        $rules     = $this->get_cache_value( $rules_key );

        if ( $rules instanceof NotFoundException ) {
            $rules = \array_fill_keys( \array_values( $this->get_permissions() ), array() );

            $granting_rules = $this->get_granting_rules();
            foreach ( $granting_rules as $role => $granting_rule ) {
                if ( 'all' === $granting_rule ) {
                    foreach ( $rules as &$roles ) {
                        $roles[] = $role;
                    }
                } elseif ( \is_array( $granting_rule ) && isset( $granting_rule['rule'], $granting_rule['permissions'] ) ) {
                    if ( 'include' === $granting_rule['rule'] ) {
                        foreach ( $granting_rule['permissions'] as $permission ) {
                            if ( isset( $rules[ $permission ] ) ) {
                                $rules[ $permission ][] = $role;
                            }
                        }
                    } elseif ( 'exclude' === $granting_rule['rule'] ) {
                        foreach ( $rules as $permission => &$roles ) {
                            if ( ! \in_array( $permission, $granting_rule['permissions'], true ) ) {
                                $roles[] = $role;
                            }
                        }
                    }
                }
            }

            foreach ( $this->get_children() as $child ) {
                if ( is_a( $child, self::class ) ) {
                    $rules += $child->collect_granting_rules();
                }
            }

            $this->set_cache_value( $rules_key, $rules );
        }

        return $rules;
    }

    // endregion
}