Component_Compiler   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 93
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
eloc 26
c 2
b 0
f 1
dl 0
loc 93
rs 10
wmc 8

4 Methods

Rating   Name   Duplication   Size   Complexity  
A compile() 0 2 1
A get_annotation() 0 14 2
A get_component_path() 0 28 4
A __construct() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * The base component class.
7
 *
8
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
9
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
10
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
11
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
12
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
13
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
14
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
15
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
16
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
17
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
18
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
 *
20
 * @author Glynn Quelch <[email protected]>
21
 * @license http://www.opensource.org/licenses/mit-license.html  MIT License
22
 * @package PinkCrab\Perique\View
23
 * @since 1.2.0
24
 */
25
26
namespace PinkCrab\Perique\Services\View\Component;
27
28
use PinkCrab\Perique\Application\Hooks;
29
use PinkCrab\Perique\Services\View\View_Model;
30
use Doctrine\Common\Annotations\AnnotationReader;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Annotations\AnnotationReader was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
use Doctrine\Common\Annotations\AnnotationRegistry;
0 ignored issues
show
Bug introduced by
The type Doctrine\Common\Annotations\AnnotationRegistry was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
32
use PinkCrab\Perique\Services\View\Component\Component;
33
34
class Component_Compiler {
35
36
	/**
37
	 * The base path for components.
38
	 *
39
	 * If blank will assume views/components
40
	 *
41
	 * @var string
42
	 */
43
	private string $component_base_path;
44
45
	/**
46
	 * All component aliases..
47
	 *
48
	 * @var array<string, string>
49
	 */
50
	private array $component_aliases = array();
51
52
	/**
53
	 * @param array<string, string> $component_aliases
54
	 */
55
	public function __construct( string $component_base_path = '', array $component_aliases = array() ) {
56
		$this->component_base_path = $component_base_path;
57
		$this->component_aliases   = \apply_filters( Hooks::COMPONENT_ALIASES, $component_aliases );
58
	}
59
60
	/**
61
	 * Compiles the component into a view model.
62
	 *
63
	 * @param Component $component
64
	 * @return View_Model
65
	 */
66
	public function compile( Component $component ): View_Model {
67
		return new View_Model( $this->get_component_path( $component ), $component->get_variables() );
68
	}
69
70
	/**
71
	 * Returns the path to the component.
72
	 *
73
	 * @param Component $component
74
	 * @return string
75
	 */
76
	private function get_component_path( Component $component ): string {
77
78
		// Check aliases.
79
		$aliases = \apply_filters( Hooks::COMPONENT_ALIASES, $this->component_aliases );
80
81
		if ( \array_key_exists( get_class( $component ), $this->component_aliases ) ) {
82
			return esc_attr( $aliases[ get_class( $component ) ] );
83
		}
84
85
		$from_annotation = $this->get_annotation( 'view', $component );
86
87
		// If it does have a path defined, use that.
88
		if ( ! empty( $from_annotation ) ) {
89
			return \trailingslashit( $this->component_base_path ) . $from_annotation;
90
		}
91
92
		// If the component has a defined path
93
		if ( $component->template() ) {
0 ignored issues
show
Bug introduced by
Are you sure the usage of $component->template() targeting PinkCrab\Perique\Service...t\Component::template() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
94
			return \trailingslashit( $this->component_base_path ) . $component->template();
0 ignored issues
show
Bug introduced by
Are you sure $component->template() of type void can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

94
			return \trailingslashit( $this->component_base_path ) . /** @scrutinizer ignore-type */ $component->template();
Loading history...
Bug introduced by
Are you sure the usage of $component->template() targeting PinkCrab\Perique\Service...t\Component::template() seems to always return null.

This check looks for function or method calls that always return null and whose return value is used.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
if ($a->getObject()) {

The method getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
95
		}
96
97
		// Get path based on class name.
98
		$reflect    = new \ReflectionClass( $component );
99
		$short_name = $reflect->getShortName();
100
		// Add space between capitals, make lowercase and replace underscores with dashes.
101
		$short_name = strtolower( preg_replace( '/(?<!^)[A-Z]/', '$0', $short_name ) ?? '' );
102
		$short_name = str_replace( '_', '-', $short_name );
103
		return \trailingslashit( $this->component_base_path ) . $short_name;
104
	}
105
106
	/**
107
	 * Attempts to extract a defined Annotation from component class doc block.
108
	 *
109
	 * @param string    $annotation
110
	 * @param Component $component
111
	 * @return string|null
112
	 */
113
	private function get_annotation( string $annotation, Component $component ): ?string {
114
		$reflect = new \ReflectionClass( $component );
115
		$comment = $reflect->getDocComment();
116
117
		// if no comment, return null.
118
		if ( empty( $comment ) ) {
119
			return null;
120
		}
121
122
		// Check if the comment contains the annotation "@{$annotation}" using regex.
123
		$pattern = "/@{$annotation}\s+(.*)/";
124
		preg_match( $pattern, $comment, $matches );
125
126
		return $matches[1] ?? null;
127
	}
128
}
129