Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
52.17% covered (warning)
52.17%
12 / 23
33.33% covered (danger)
33.33%
2 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
Logger_Settings_Trait
52.17% covered (warning)
52.17%
12 / 23
33.33% covered (danger)
33.33%
2 / 6
24.24
0.00% covered (danger)
0.00%
0 / 1
 get_log_level
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
4
 get_log_levels
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 get_plugin_name
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 get_plugin_slug
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 get_plugin_basename
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 get_cli_base
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 * Default function implementations for classes implementing `Logger_Settings_Interface`.
4 *
5 * These functions infer the current plugin's basename, name, log level.
6 *
7 * It is faster to provide your own implementation of each function.
8 *
9 * A Settings class should `implements Logger_Settings_Interface` and `use Logger_Settings_Trait`
10 * then override all the functions. This allows more functions to be added to the interface in future
11 * library updates without requiring projects to implement the new functions, i.e. it provides
12 * forward-compatibility.
13 *
14 * @package brianhenryie/bh-wp-logger
15 */
16
17namespace BrianHenryIE\WP_Logger;
18
19use BrianHenryIE\WP_Logger\WP_Includes\CLI;
20use Exception;
21use Psr\Log\LogLevel;
22use ReflectionClass;
23
24/**
25 * Default function implementations for Logger_Settings_Interface.
26 *
27 * @see Logger_Settings_Interface
28 */
29trait Logger_Settings_Trait {
30
31    /**
32     * The log level to use.
33     *
34     * Default is Info.
35     * Looks for saved value in `get_option( 'my-plugin-slug_log_level' ).
36     *
37     * @see LogLevel
38     */
39    public function get_log_level(): string {
40        try {
41            $saved_option = get_option( $this->get_plugin_slug() . '_log_level' );
42            return is_string( $saved_option )
43                    && in_array(
44                        $saved_option,
45                        $this->get_log_levels(),
46                        true
47                    )
48                    ? $saved_option
49                    : LogLevel::INFO;
50        } catch ( Exception ) {
51            return LogLevel::INFO;
52        }
53    }
54
55    /**
56     * @var string[] $log_levels
57     */
58    protected array $log_levels;
59
60    /**
61     * Returns all valid log levels. Only computes it once.
62     *
63     * @return string[]
64     */
65    protected function get_log_levels(): array {
66        if ( ! isset( $this->log_levels ) ) {
67            $this->log_levels = array_values( ( new ReflectionClass( LogLevel::class ) )->getConstants() );
68        }
69        return $this->log_levels;
70    }
71
72    /**
73     * The plugin friendly name to use in UIs.
74     *
75     * @throws Exception When the basename cannot be determined.
76     */
77    public function get_plugin_name(): string {
78        $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $this->get_plugin_basename() );
79        return $plugin_data['Name'];
80    }
81
82    /**
83     * The plugin slug. I.e. the plugin directory name. Used in URLs and wp_options.
84     *
85     * @throws Exception When the basename cannot be determined.
86     */
87    public function get_plugin_slug(): string {
88        return explode( '/', $this->get_plugin_basename() )[0];
89    }
90
91    /**
92     * The plugin basename. Used to add the Logs link on `plugins.php`.
93     *
94     * @see https://core.trac.wordpress.org/ticket/42670
95     *
96     * @throws Exception When it cannot be determined. I.e. a symlink inside a symlink.
97     */
98    public function get_plugin_basename(): string {
99
100        /**
101         * TODO: The following might work but there are known issues around symlinks that need to be tested and handled correctly.
102         *
103         * @see  https://core.trac.wordpress.org/ticket/42670
104         */
105
106        $wp_plugin_basename = plugin_basename( __DIR__ );
107
108        /** @var array<string, array<string>> $plugin_data */
109        $plugin_data = get_plugins( explode( '/', $wp_plugin_basename )[0] );
110
111        if ( 1 === count( $plugin_data ) ) {
112            return array_key_first( $plugin_data );
113        }
114
115        throw new Exception( 'Plugin installed in an unusual directory.' );
116    }
117
118    /**
119     * Default CLI commands to use the plugin slug as the base for commands.
120     *
121     * @see CLI
122     */
123    public function get_cli_base(): ?string {
124        return $this->get_plugin_slug();
125    }
126}