Completed
Push — master ( b56cf6...b21678 )
by Askupa
01:23
created

AbstractComponent.php (6 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Amarkal\UI;
4
5
/**
6
 * Defines an abstract UI component
7
 */
8
abstract class AbstractComponent
9
extends Template
0 ignored issues
show
The extends keyword must be on the same line as the class name
Loading history...
10
{
11
    /**
12
     * This template is used to generate the name for this component. the token 
13
     * {{name}} will be replaced by the component's name during runtime.
14
     * 
15
     * @var string
16
     */
17
    public $name_template = '{{name}}';
18
    
19
    /**
20
     * This template is used to generate the name for this component when it is
21
     * used as a child component in a composite component. The token 
22
     * {{parent_name}} will be replaced with the name of the parent (composite)
23
     * component.
24
     * 
25
     * @var string
26
     */
27
    public $composite_name_template = '{{parent_name}}[{{name}}]';
28
    
29
    /**
30
     * A list of HTML classes to be added to the wrapper div of this component.
31
     *
32
     * @var array
33
     */
34
    public $html_classes = array();
35
    
36
    /**
37
     * Constructor
38
     * 
39
     * @param array $model
40
     */
41
    public function __construct( array $model = array() ) 
42
    {
43
        parent::__construct($model);
44
        
45
        $this->add_html_class(sprintf(
46
            'amarkal-ui-component amarkal-ui-component-%s',
47
            $this->component_type
0 ignored issues
show
The property component_type does not exist on object<Amarkal\UI\AbstractComponent>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
48
        ));
49
50
        if($this instanceof DisableableComponentInterface && $this->disabled)
0 ignored issues
show
The property disabled does not exist on object<Amarkal\UI\AbstractComponent>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
51
        {
52
            $this->add_html_class('amarkal-ui-disabled');
53
        }
54
        
55
        $this->on_created();
56
    }
57
    
58
    /**
59
     * The default model to use when none is provided to the constructor.
60
     * This method should be overriden by child class to define the default
61
     * model.
62
     * 
63
     * @return array
64
     */
65
    public function default_model()
66
    {
67
        return array();
68
    }
69
    
70
    /**
71
     * The list of required model arguments.
72
     * This method should be overriden by child class to specify required model
73
     * arguments.
74
     * 
75
     * @return array
76
     */
77
    public function required_arguments()
78
    {
79
        return array();
80
    }
81
    
82
    /**
83
     * Set the model data for this component.
84
     * 
85
     * @return array
86
     */
87
    public function set_model( $model )
88
    {
89
        // Check that the required arguments are provided.
90
        foreach( $this->required_arguments() as $key )
91
        {
92
            if ( !isset($model[$key]) )
93
            {
94
                throw new \RuntimeException('The required argument "'.$key.'" was not provided for '.get_called_class());
95
            }
96
        }
97
        
98
        // Assign the name of the component as the id if no id was specified
99
        if( !isset($model['id']) && isset($model['name']) )
100
        {
101
            $model['id'] = $model['name'];
102
        }
103
104
        // A name must be specified when a component has a visibility condition
105
        if( isset($model['show']) && !isset($model['name']) )
106
        {
107
            throw new \RuntimeException('Components with a visibility condition (a "show" argument) must have a name');
108
        }
109
        
110
        $this->model = array_merge( $this->default_model(), $model );
111
    }
112
    
113
    /**
114
     * Get the name for this component by parsing the name template.
115
     * 
116
     * @return string
117
     */
118
    public function get_name()
119
    {
120
        return \str_replace('{{name}}', $this->name, $this->name_template);
0 ignored issues
show
The property name does not exist on object<Amarkal\UI\AbstractComponent>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
121
    }
122
    
123
    /**
124
     * Add an HTML class to the list of HTML classes to be printed when the
125
     * component is rendered. 
126
     * 
127
     * @param string $class
128
     */
129
    public function add_html_class( $class )
130
    {
131
        if( !in_array($class, $this->html_classes) )
132
        {
133
            $this->html_classes[] = $class;
134
        }
135
    }
136
    
137
    /**
138
     * Remove an HTML class to the list of HTML classes to be printed when the
139
     * component is rendered. 
140
     * 
141
     * @param string $class
142
     */
143
    public function remove_html_class( $class )
144
    {
145
        $i = 0;
146
        foreach( $this->html_classes as $c )
147
        {
148
            if( $c === $class )
149
            {
150
                array_splice($this->html_classes,$i,1);
151
                break;
152
            }
153
            $i++;
154
        }
155
    }
156
    
157
    /**
158
     * Set the validity of this component if it supports validation.
159
     * 
160
     * @param type $validity
161
     */
162
    Public function set_validity( $validity )
163
    {
164
        $this->validity = $validity;
0 ignored issues
show
The property validity does not exist on object<Amarkal\UI\AbstractComponent>. Since you implemented __set, maybe consider adding a @property annotation.

Since your code implements the magic setter _set, this function will be called for any write access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

Since the property has write access only, you can use the @property-write annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
165
        if($validity === $this::INVALID)
166
        {
167
            $this->add_html_class('amarkal-ui-component-error');
168
        }
169
    }
170
    
171
    /**
172
     * Generate common UI component wrapper attributes
173
     */
174
    public function component_attributes()
175
    {
176
        return sprintf(
177
            'class="%s" amarkal-component-name="%s"',
178
            implode(' ', $this->html_classes),
179
            $this->name
0 ignored issues
show
The property name does not exist on object<Amarkal\UI\AbstractComponent>. Since you implemented __get, maybe consider adding a @property annotation.

Since your code implements the magic getter _get, this function will be called for any read access on an undefined variable. You can add the @property annotation to your class or interface to document the existence of this variable.

<?php

/**
 * @property int $x
 * @property int $y
 * @property string $text
 */
class MyLabel
{
    private $properties;

    private $allowedProperties = array('x', 'y', 'text');

    public function __get($name)
    {
        if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
            return $properties[$name];
        } else {
            return null;
        }
    }

    public function __set($name, $value)
    {
        if (in_array($name, $this->allowedProperties)) {
            $properties[$name] = $value;
        } else {
            throw new \LogicException("Property $name is not defined.");
        }
    }

}

If the property has read access only, you can use the @property-read annotation instead.

Of course, you may also just have mistyped another name, in which case you should fix the error.

See also the PhpDoc documentation for @property.

Loading history...
180
        );
181
    }
182
    
183
    /**
184
     * Enqueue component's script and render it.
185
     * 
186
     * {@inheritdoc}
187
     */
188
    public function render( $echo = false )
189
    {
190
        $this->enqueue_scripts();
191
        
192
        ob_start();
193
        include dirname(__FILE__).'/AbstractComponent.phtml';
194
        $html = ob_get_clean();
195
196
        if( !$echo )
197
        {
198
            return $html;
199
        }
200
        echo $html;
201
    }
202
    
203
    /**
204
     * Enqueue styles/scripts required for this element.
205
     */
206
    public function enqueue_scripts()
207
    {
208
        \wp_enqueue_script('amarkal-ui');
209
        \wp_enqueue_style('amarkal-ui');
210
    }
211
    
212
    /**
213
     * A hook that is called once the component has been created.
214
     */
215
    protected function on_created() {}
216
}