Completed
Push — master ( 4170f5...82b95f )
by Nekrasov
02:28
created

AbstractWidgetFactory::instantiateWidget()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 24
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.5125
c 0
b 0
f 0
cc 5
eloc 14
nc 6
nop 1
1
<?php
2
3
namespace Arrilot\Widgets\Factories;
4
5
use Arrilot\Widgets\AbstractWidget;
6
use Arrilot\Widgets\Contracts\ApplicationWrapperContract;
7
use Arrilot\Widgets\Misc\EncryptException;
8
use Arrilot\Widgets\Misc\InvalidWidgetClassException;
9
use Arrilot\Widgets\Misc\ViewExpressionTrait;
10
use Arrilot\Widgets\WidgetId;
11
12
abstract class AbstractWidgetFactory
13
{
14
    use ViewExpressionTrait;
15
16
    /**
17
     * Widget object to work with.
18
     *
19
     * @var AbstractWidget
20
     */
21
    protected $widget;
22
23
    /**
24
     * Widget configuration array.
25
     *
26
     * @var array
27
     */
28
    protected $widgetConfig;
29
30
    /**
31
     * The name of the widget being called.
32
     *
33
     * @var string
34
     */
35
    public $widgetName;
36
37
    /**
38
     * Array of widget parameters excluding the first one (config).
39
     *
40
     * @var array
41
     */
42
    public $widgetParams;
43
44
    /**
45
     * Array of widget parameters including the first one (config).
46
     *
47
     * @var array
48
     */
49
    public $widgetFullParams;
50
51
    /**
52
     * Laravel application wrapper for better testability.
53
     *
54
     * @var ApplicationWrapperContract;
55
     */
56
    public $app;
57
58
    /**
59
     * Another factory that produces some javascript.
60
     *
61
     * @var JavascriptFactory
62
     */
63
    protected $javascriptFactory;
64
65
    /**
66
     * The flag for not wrapping content in a special container.
67
     *
68
     * @var bool
69
     */
70
    public static $skipWidgetContainer = false;
71
72
    /**
73
     * The flag for not wrapping content in a special container.
74
     *
75
     * @var bool
76
     */
77
    public static $allowOnlyWidgetsWithDisabledEncryption = false;
78
79
    /**
80
     * Constructor.
81
     *
82
     * @param ApplicationWrapperContract $app
83
     */
84
    public function __construct(ApplicationWrapperContract $app)
85
    {
86
        $this->app = $app;
87
88
        $this->javascriptFactory = new JavascriptFactory($this);
89
    }
90
91
    /**
92
     * Magic method that catches all widget calls.
93
     *
94
     * @param string $widgetName
95
     * @param array  $params
96
     *
97
     * @return mixed
98
     */
99
    public function __call($widgetName, array $params = [])
100
    {
101
        array_unshift($params, $widgetName);
102
103
        return call_user_func_array([$this, 'run'], $params);
104
    }
105
106
    /**
107
     * Set class properties and instantiate a widget object.
108
     *
109
     * @param $params
110
     *
111
     * @throws InvalidWidgetClassException
112
     * @throws EncryptException
113
     */
114
    protected function instantiateWidget(array $params = [])
115
    {
116
        WidgetId::increment();
117
118
        $this->widgetName = $this->parseFullWidgetNameFromString(array_shift($params));
119
        $this->widgetFullParams = $params;
120
        $this->widgetConfig = (array) array_shift($params);
121
        $this->widgetParams = $params;
122
123
        $rootNamespace = $this->app->config('laravel-widgets.default_namespace', $this->app->getNamespace().'Widgets');
124
125
        $fqcn = $rootNamespace.'\\'.$this->widgetName;
126
        $widgetClass = class_exists($fqcn) ? $fqcn : $this->widgetName;
127
128
        if (!is_subclass_of($widgetClass, 'Arrilot\Widgets\AbstractWidget')) {
129
            throw new InvalidWidgetClassException('Class "'.$widgetClass.'" must exist and extend "Arrilot\Widgets\AbstractWidget" class');
130
        }
131
132
        $this->widget = new $widgetClass($this->widgetConfig);
133
134
        if (static::$allowOnlyWidgetsWithDisabledEncryption && $this->widget->encryptParams) {
135
            throw new EncryptException('Widget "'.$widgetClass.'" was not called properly');
136
        }
137
    }
138
139
    /**
140
     * Convert stuff like 'profile.feedWidget' to 'Profile\FeedWidget'.
141
     *
142
     * @param $widgetName
143
     *
144
     * @return string
145
     */
146
    protected function parseFullWidgetNameFromString($widgetName)
147
    {
148
        return studly_case(str_replace('.', '\\', $widgetName));
149
    }
150
151
    /**
152
     * Wrap the given content in a container if it's not an ajax call.
153
     *
154
     * @param $content
155
     *
156
     * @return string
157
     */
158
    protected function wrapContentInContainer($content)
159
    {
160
        if (self::$skipWidgetContainer) {
161
            return $content;
162
        }
163
164
        $container = $this->widget->container();
165
        if (empty($container['element'])) {
166
            $container['element'] = 'div';
167
        }
168
169
        return '<'.$container['element'].' id="'.$this->javascriptFactory->getContainerId().'" '.$container['attributes'].'>'.$content.'</'.$container['element'].'>';
170
    }
171
172
    /**
173
     * Encrypt widget params to be transported via HTTP.
174
     *
175
     * @param string $params
176
     *
177
     * @return string
178
     */
179
    public function encryptWidgetParams($params)
180
    {
181
        return $this->app->make('encrypter')->encrypt($params);
182
    }
183
184
    /**
185
     * Decrypt widget params that were transported via HTTP.
186
     *
187
     * @param string $params
188
     *
189
     * @return string
190
     */
191
    public function decryptWidgetParams($params)
192
    {
193
        return $this->app->make('encrypter')->decrypt($params);
194
    }
195
}
196