Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
3.80% covered (danger)
3.80%
3 / 79
7.69% covered (danger)
7.69%
1 / 13
CRAP
0.00% covered (danger)
0.00%
0 / 1
Features
3.80% covered (danger)
3.80%
3 / 79
7.69% covered (danger)
7.69%
1 / 13
413.64
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
12
 initFeatures
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
12
 registerRoutes
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 registerCLI
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
2
 assets
0.00% covered (danger)
0.00%
0 / 22
0.00% covered (danger)
0.00%
0 / 1
2
 defaultIsEnabledFilter
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 getInstance
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 getFeatures
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getToggleableFeatures
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
 getFeatureList
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFeature
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 hasFeature
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 load_text_domain
0.00% covered (danger)
0.00%
0 / 11
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2namespace NewfoldLabs\WP\Module\Features;
3
4use NewfoldLabs\WP\Module\Features\Registry;
5use NewfoldLabs\WP\Module\Features\FeaturesAPI;
6
7use function NewfoldLabs\WP\ModuleLoader\container;
8
9/**
10 * This class Features functionality.
11 **/
12class Features {
13
14    /**
15     * Singleton instance
16     *
17     * @var Features
18     */
19    private static $instance = null;
20
21    /**
22     * Registry
23     *
24     * @var Registry
25     */
26    private static $registry = null;
27
28    /**
29     * Module Path
30     *
31     * @var String
32     */
33    private static $module_path = null;
34
35    /**
36     * Constructor.
37     */
38    private function __construct() {
39
40        // Create registry
41        self::$registry = new Registry();
42
43        self::$module_path = container()->plugin()->url . 'vendor/newfold-labs/wp-module-features';
44
45        if ( function_exists( 'add_action' ) ) {
46
47            // Find and add all features to registry
48            add_action( 'plugins_loaded', array( __CLASS__, 'initFeatures' ), 3 );
49
50            // Register API endpoints
51            add_action( 'rest_api_init', array( __CLASS__, 'registerRoutes' ) );
52
53            // Add CLI commands
54            add_action( 'cli_init', array( __CLASS__, 'registerCLI' ) );
55
56            // Register API script and localized values
57            add_action( 'admin_enqueue_scripts', array( __CLASS__, 'assets' ) );
58
59            \add_action( 'init', array( __CLASS__, 'load_text_domain' ), 100 );
60        }
61
62        // Add default filter to make any feature null value return false
63        if ( function_exists( 'add_filter' ) ) {
64            add_filter(
65                'newfold/features/filter/isEnabled',
66                array( __CLASS__, 'defaultIsEnabledFilter' ),
67                99, // low priority so modules can override easily if needed
68                1
69            );
70        }
71    }
72
73    /**
74     * Find and add all feature classes to the registry
75     */
76    public static function initFeatures() {
77        // Find extended instances of the Feature class and add to the Registry
78        $features = apply_filters( 'newfold/features/filter/register', array() );
79        foreach ( $features as $feature ) {
80            // Validate that the feature extends this
81            if ( is_subclass_of( $feature, 'NewfoldLabs\WP\Module\Features\Feature' ) ) {
82                // add class to registry and instantiate
83                self::$registry->set( $feature );
84            }
85        }
86    }
87
88    /**
89     * Register routes
90     */
91    public static function registerRoutes() {
92        new FeaturesAPI();
93    }
94
95    /**
96     * Add CLI commands
97     */
98    public static function registerCLI() {
99        \WP_CLI::add_command(
100            'newfold features',
101            'NewfoldLabs\WP\Module\Features\FeaturesCLI',
102            array(
103                'shortdesc' => 'Operations for Newfold Features.',
104                'longdesc'  => 'Internal commands to handle features.' .
105                                PHP_EOL . 'Subcommands: all, enable, disable, isEnabled.',
106            )
107        );
108    }
109
110    /**
111     * Register API script and localized values
112     */
113    public static function assets() {
114
115        // Register features API script
116        $scriptPath = container()->plugin()->url . 'vendor/newfold-labs/wp-module-features/static/js/features.js';
117        wp_register_script(
118            'newfold-features',
119            $scriptPath,
120            array( 'wp-api-fetch', 'wp-i18n' ),
121            container()->plugin()->version,
122            true
123        );
124
125        // Localized Script with initial feature values
126        wp_localize_script(
127            'newfold-features',
128            'NewfoldFeatures',
129            array(
130                'features'  => self::getFeatures(),
131                'togglable' => self::getToggleableFeatures(),
132                'restUrl'   => esc_url_raw( rest_url() ) . 'newfold-features/v1',
133            )
134        );
135
136        \wp_set_script_translations(
137            'newfold-features',
138            'wp-module-features',
139            self::$module_path . '/languages'
140        );
141    }
142    /**
143     * Add default filter to make any feature null value return false
144     *
145     * @param boolean $value The value to set.
146     */
147    public static function defaultIsEnabledFilter( $value ) {
148        // if feature state is null, return false
149        if ( ! isset( $value ) ) {
150            $value = false;
151        }
152        return $value;
153    }
154
155    /**
156     * Get instance for singleton Features
157     *
158     * @return Features instance
159     */
160    public static function getInstance() {
161        if ( null === self::$instance ) {
162            self::$instance = new Features();
163        }
164        return self::$instance;
165    }
166
167    /**
168     * Get All Features and filter states
169     *
170     * @return Array list of features and enabled states (key:name value:enabled)
171     */
172    public static function getFeatures() {
173        $features = array();
174        foreach ( self::getFeatureList() as $feature ) {
175            $features[ $feature ] = Features::getInstance()->getFeature( $feature )->isEnabled();
176        }
177        return $features;
178    }
179
180    /**
181     * Get All Features and filter states
182     *
183     * @return Array list of features and enabled states (key:name value:enabled)
184     */
185    public static function getToggleableFeatures() {
186        $features = array();
187        foreach ( self::getFeatureList() as $feature ) {
188            $features[ $feature ] = Features::getInstance()->getFeature( $feature )->isTogglable();
189        }
190        return $features;
191    }
192
193    /**
194     * Get feature list
195     *
196     * @return Array list of features
197     */
198    public static function getFeatureList() {
199        return self::$registry->keys();
200    }
201
202    /**
203     * Get Feature
204     *
205     * @param string $name the name of the feature
206     * @return Feature instance
207     */
208    public static function getFeature( $name ) {
209        return self::$registry->get( $name );
210    }
211
212    /**
213     * Has Feature
214     *
215     * @param string $name the name of the feature
216     * @return boolean true if feature exists, false otherwise
217     */
218    public static function hasFeature( $name ) {
219        return self::$registry->has( $name );
220    }
221
222    /**
223     * Load text domain for Module
224     *
225     * @return void
226     */
227    public static function load_text_domain() {
228
229        $module_path = container()->plugin()->url . 'vendor/newfold-labs/wp-module-features';
230
231        \load_plugin_textdomain(
232            'wp-module-features',
233            false,
234            $module_path . '/languages'
235        );
236
237        \load_script_textdomain(
238            'newfold-features',
239            'wp-module-features',
240            self::$module_path . '/languages'
241        );
242    }
243}