Completed
Push — master ( 6e51f4...6552db )
by Vitaly
05:02
created

View   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 162
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 2

Test Coverage

Coverage 95.12%

Importance

Changes 10
Bugs 1 Features 6
Metric Value
wmc 15
c 10
b 1
f 6
lcom 2
cbo 2
dl 0
loc 162
ccs 39
cts 41
cp 0.9512
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A view() 0 9 2
B output() 0 29 3
A __get() 0 8 2
A __call() 0 8 2
A set() 0 14 4
A setRenderableObject() 0 9 2
1
<?php
2
/**
3
 * Created by Vitaly Iegorov <[email protected]>.
4
 * on 18.02.16 at 14:15
5
 */
6
namespace samsonframework\view;
7
8
use samsonframework\core\RenderInterface;
9
use samsonframework\core\ViewInterface;
10
use samsonframework\view\exception\VariableKeyNotFound;
11
use samsonframework\view\exception\ViewFileNotFound;
12
13
/**
14
 * View class for rendering.
15
 * @package samsonframework\view
16
 */
17
class View implements ViewInterface
18
{
19
    /** Default view file extension */
20
    const DEFAULT_EXT = 'vphp';
21
22
    /** @var array Collection of $key => $value view data */
23
    protected $data = array();
24
25
    /** @var string Full path to view file */
26
    protected $file;
27
28
    /** @var string View source code */
29
    protected $source;
30
31
    /** @var string Rendered view contents */
32
    protected $output;
33
34
    /**
35
     * Set current view for rendering.
36
     * Method searches for the shortest matching view path by $pathPattern,
37
     * from loaded views.
38
     *
39
     * Module saves all view data that has been set to a specific view in appropriate
40
     * view data collection entry. By default module creates vied data entry - VD_POINTER_DEF,
41
     * and until any call of iModule::view() or iModule::output(), all data that is iModule::set(),
42
     * is stored to that location.
43
     *
44
     * On the first call of iModule::view() or iModule::output(), this method changes the view data
45
     * pointer to actual relative view path, and copies(actually just sets view data pointer) all view
46
     * data set before to new view data pointer. This guarantees backward compatibility and gives
47
     * opportunity not to set the view path before setting view data to it.
48
     *
49
     * @param string $pathPattern Path pattern for view searching
50
     *
51
     * @return $this Chaining
52
     * @throws \Exception
53
     */
54 2
    public function view($pathPattern)
55
    {
56 2
        if (file_exists($pathPattern)) {
57 2
            $this->file = $pathPattern;
58 2
            return $this;
59
        }
60
61 1
        throw new ViewFileNotFound($pathPattern);
62
    }
63
64
    /**
65
     * Render current view.
66
     * Method uses current view context and outputs rendering
67
     * result.
68
     *
69
     * @return string Rendered view
70
     */
71 1
    public function output()
72
    {
73
        // Start buffering
74 1
        ob_start();
75
76
        // Make variables accessible directly in view
77 1
        extract($this->data);
78
79
        // Render view from source
80 1
        if (!empty($this->source)) {
81
            eval(' ?>' . $this->source . '<?php ');
82
        } else { // Render view from file
83 1
            include($this->file);
84
        }
85
86
        // Store buffer output
87 1
        $this->output = ob_get_contents();
88
89
        // Clear buffer
90 1
        ob_end_clean();
91
92
        // Remove variables from context to free memory
93 1
        foreach ($this->data as $key => $value) {
94 1
            unset($key);
95 1
        }
96
97
        // Returned rendered view
98 1
        return $this->output;
99
    }
100
101
    /**
102
     * Magic method for getting view variables.
103
     *
104
     * @param string $name Variable key
105
     *
106
     * @return mixed Value
107
     * @throws VariableKeyNotFound
108
     */
109 5
    public function __get($name)
110
    {
111 5
        if (array_key_exists($name, $this->data)) {
112 5
            return $this->data[$name];
113
        }
114
115 1
        throw new VariableKeyNotFound($name);
116
    }
117
118
    /**
119
     * Magic method for setting view variables.
120
     *
121
     * @param string $name      Variable key
122
     * @param array  $arguments Variable value
123
     *
124
     * @return $this Chaining
125
     * @throws VariableKeyNotFound
126
     */
127 1
    public function __call($name, $arguments)
128
    {
129 1
        if (count($arguments)) {
130 1
            $this->set($arguments[0], $name);
131 1
        }
132
133 1
        return $this;
134
    }
135
136
    /**
137
     * Set view variable.
138
     *
139
     * Passing an array as $value will add array key => values into current
140
     * view data collection. If $key is passed then an array variable with this
141
     * key will be added to view data collection beside adding array key => values.
142
     *
143
     * @param mixed       $value Variable value
144
     * @param string|null $key   Variable key\prefix for objects and arrays
145
     *
146
     * @return $this Chaining
147
     */
148 5
    public function set($value, $key = null)
149
    {
150
        // RenderInterface implementation
151 5
        if (is_object($value) && is_a($value, RenderInterface::class)) {
152 3
            $this->setRenderableObject($value, $key);
153 5
        } elseif (is_array($value)) { // Merge array into view data
154 2
            $this->data = array_merge($this->data, $value);
155 2
        }
156
157
        // Store key value
158 5
        $this->data[$key] = $value;
159
160 5
        return $this;
161
    }
162
163
    /**
164
     * Set renderable object as view variable.
165
     *
166
     * @param mixed       $object Object instance for rendering
167
     * @param string|null $key    Variable key\prefix for objects and arrays
168
     */
169 3
    protected function setRenderableObject($object, $key)
170
    {
171
        /** @var RenderInterface $object */
172
        // Generate objects view array data and merge it with view data
173 3
        $this->data = array_merge(
174 3
            $this->data,
175 3
            $object->toView(null !== $key ? $key : get_class($object))
176 3
        );
177 3
    }
178
}
179