Widget::factoryBlock()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 5
dl 0
loc 9
rs 10
c 1
b 0
f 0
cc 2
nc 2
nop 4
ccs 0
cts 8
cp 0
crap 6
1
<?php
2
3
namespace neon\cms\components;
4
5
6
use neon\core\helpers\Arr;
7
use neon\core\helpers\Str;
8
use yii\helpers\ArrayHelper;
9
use neon\cms\components\Daedalus;
10
11
class Widget
12
{
13
	/**
14
	 * @var array
15
	 */
16
	public $params = [];
17
18
	/**
19
	 * @var Smarty_Internal_Template
0 ignored issues
show
Bug introduced by
The type neon\cms\components\Smarty_Internal_Template was not found. Did you mean Smarty_Internal_Template? If so, make sure to prefix the type with \.
Loading history...
20
	 */
21
	protected $template;
22
23
	/**
24
	 * The rendering system object
25
	 * @var neon\cms\components\Renderer
0 ignored issues
show
Bug introduced by
The type neon\cms\components\neon\cms\components\Renderer was not found. Did you mean neon\cms\components\Renderer? If so, make sure to prefix the type with \.
Loading history...
26
	 */
27
	protected $renderer = null;
28
29
	/**
30
	 * The required data request for the widget
31
	 * @var array
32
	 */
33
	protected $data = [];
34
35
	/**
36
	 * For dynamic requests, the meta information about the request
37
	 * Currently 'start','length' and 'total' for pagination. Total is only
38
	 * set if a request was made for it when 'start' was 0
39
	 * @var array
40
	 */
41
	protected $meta = [];
42
43
	/**
44
	 * The page component this widget is being rendered for
45
	 * @var neon\cms\components\Page
0 ignored issues
show
Bug introduced by
The type neon\cms\components\neon\cms\components\Page was not found. Did you mean neon\cms\components\Page? If so, make sure to prefix the type with \.
Loading history...
46
	 */
47
	public static $page;
48
49
	/**
50
	 * If true then this is a static content request widget. Otherwise
51
	 * it's a dynamic daedalus object
52
	 * @var boolean
53
	 */
54
	protected $isStatic = false;
55
56
57
	/**
58
	 * The widget factory function
59
	 * Creates a new widget object with appropriate params and tells it to render
60
	 *
61
	 * @param array $params
62
	 *   type: [required] - this is auto-populated with the tag name
63
	 *   file: [optional] the template file - default widgets/[type].tpl if not specified
64
	 *   wys|wysiwyg: [optional] - if set then this uses the wysiwyg version of the editor
65
	 *
66
	 *  Data request:
67
	 *  -------------------
68
	 *  Data requests can be done in one of three ways. These are all used to generate
69
	 *  a Daedalus request. For full details @see IDdsObjectManagement.
70
	 *
71
	 *    1. Site and Page specfic static content - this lets you request page editable
72
	 *      'static' content using the 'key' and optional 'page' & 'content' parameters. This
73
	 *      is static content as once editing is complete it doesn't change per view
74
	 *
75
	 *      key: [required] - if set this is combined with the type to build a
76
	 *        data request key from the static data
77
	 *      page: [optional] - set to true - this further specifies the data request
78
	 *        key to be page specific
79
	 *      content: [optional] - if set use this as the default content
80
	 *
81
	 *    2. dds_xxx - these let you get hold of page dynamic data - i.e. data that can
82
	 *      change each time you view the page e.g. lists of people.
83
	 *
84
	 *      dds | dds_class | dds_page: [one of these is required]
85
	 *        this is the dynamic data class you want to use. If you just set dds then this
86
	 *        assumes the class required is the widget type otherwise it uses the dds_class
87
	 *        provided. If you just set dds_page then it assumes the dds_class is the type
88
	 *        and that a page filter is added.
89
	 *
90
	 *      dds_page: [optiona] - if set then a page filter is added to the class
91
	 *        @see Daedalus 'page' attribute for details
92
	 *
93
	 *      dds_filter: [optional] - this is a list of filters that can be applied
94
	 *        to the request
95
	 *        @see Daedalus 'filter' attribute for details
96
	 *
97
	 *     dds_order: [optional] - set the order as a series of fields and direction
98
	 *        e.g. 'field1':'ASC', 'field2':'DESC'
99
	 *        @see Daedalus 'order' attribute for details
100
	 *
101
	 *     dds_limit: [optional] - set optional 'start', 'length', 'total' sections.
102
	 *        @see Daedalus 'limit' attribute for details
103
	 *
104
	 *   3. Using the data parameter - you can set the data string directly to be passed
105
	 *     through to Daedalus. You will need to know the @see IDdsObjectManagement
106
	 *     required syntax to use this directly.
107
	 *
108
	 *     This will be overridden by the other methods if you use them.
109
	 *
110
	 * @param \Smarty_Internal_Template  $template
111
	 * @return string
112
	 */
113
	public static function factory($params, $template)
114
	{
115
		$widget = new static();
116
		$defaults = [];
117
		if (isset($params['type'])) {
118
			$defaults['type'] = $params['type'];
119
			// path to the file is determined by the theme hierarchy
120
			$defaults['file'] = $params['type'] . '.tpl';
121
			if (isset($params['key'])) {
122
				self::buildDataFromCmsKeyAttributes($params);
123
			}
124
 		}
125
		 
126
		if (isset($params['dds']) || isset($params['dds_page']) || isset($params['dds_class']))
127
			Daedalus::buildDataFromDdsAttributes($params);
128
		$resolvedParams = Arr::merge($defaults, $params);
129
		return $widget->render($resolvedParams, $template);
130
	}
131
132
	/**
133
	 * Create a Block Widget and get it to render
134
	 *
135
	 * @param $params
136
	 * @param $content
137
	 * @param $smarty
138
	 * @param $repeat
139
	 */
140
	public static function factoryBlock($params, $content, &$template, &$repeat)
0 ignored issues
show
Unused Code introduced by
The parameter $repeat is not used and could be removed. ( Ignorable by Annotation )

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

140
	public static function factoryBlock($params, $content, &$template, /** @scrutinizer ignore-unused */ &$repeat)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
141
	{
142
		$widget = new static();
143
		if ($content == null) {
144
			// dont bother doing anything
145
			return;
146
		}
147
		$params['content'] = $content;
148
		return $widget->render($params, $template);
149
	}
150
151
	/**
152
	 * Create a static content block widget and get it to render
153
	 * The default content can be overridden by the user through
154
	 * the Cobe editor and that content will be used instead if
155
	 * it is set.
156
	 *
157
	 * @param $params
158
	 *   key - the key that is used to identify this content in the
159
	 *     static content table.
160
	 *   wys - if set then wysiwyg is set to this value. If not set
161
	 *     then this is defaults to true
162
	 * @param $content
163
	 * @param $smarty
164
	 * @param $repeat
165
	 */
166
	public static function staticBlock($params, $content, &$template, &$repeat)
0 ignored issues
show
Unused Code introduced by
The parameter $repeat is not used and could be removed. ( Ignorable by Annotation )

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

166
	public static function staticBlock($params, $content, &$template, /** @scrutinizer ignore-unused */ &$repeat)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
167
	{
168
		$widget = new static();
169
		if ($content == null) {
170
			return;
171
		}
172
		// scb = static content block
173
		$params['type'] = '_scb';
174
		if (isset($params['key']))
175
			self::buildDataFromCmsKeyAttributes($params);
176
		$params['content'] = $content;
177
		$params['wys'] = (isset($params['wys']) ? $params['wys'] : true);
178
		return $widget->render($params, $template);
179
	}
180
181
	/**
182
	 * @return \neon\cms\components\Page
183
	 */
184
	public function getPage()
185
	{
186
		return self::$page;
187
	}
188
189
	/**
190
	 * Render a widget.
191
	 * The widget checks to see if it has a data request to make. If it does then
192
	 * it contacts the page and requests the data. If this is available then it
193
	 * continues to render. If it isn't available it returns a stub placeholder for
194
	 *
195
	 * @param $params
196
	 * @param $template
197
	 * @return string
198
	 */
199
	public function render($params, $template)
200
	{
201
		$this->params = $params;
202
		$this->isStatic = isset($params['is_static']) ? $params['is_static'] : false;
203
		$this->template = $template;
204
		$this->renderer = $template->smarty;
205
206
		// if we need data and are waiting for it from DDS then we output a
207
		// placeholder tag and do nothing else
208
		$data = [];
209
		if (($dataRequest = $this->getDataRequest()) !== null) {
0 ignored issues
show
introduced by
The condition $dataRequest = $this->getDataRequest() !== null is always true.
Loading history...
210
			$id = $meta = null;
211
			if (!$this->getPage()->requestWidgetData($dataRequest, $data, $id, $this->isStatic, $meta))
212
				return $id;
213
			$this->saveData($data);
214
			$this->saveDataMetaInformation($meta);
215
		}
216
		// so now we have everything we need and we render ourselves (hoorah)
217
		$ret = $this->doRender();
218
		return $ret;
219
	}
220
221
	/**
222
	 * Do the render - this can be overridden in classes that do not require
223
	 * the renderer to render their template
224
	 * @return html
0 ignored issues
show
Bug introduced by
The type neon\cms\components\html 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...
225
	 */
226
	protected function doRender()
227
	{
228
		// store template files that are reused multiple times during a render
229
		static $templates = [];
230
		if ($this->isStatic) {
231
			$content = isset($this->data['content']) ? $this->data['content'] : $this->params['content'];
232
			return $this->createStaticEditable($content);
233
		} else {
234
			$file = $this->params['file'];
235
			$this->params['hasData'] = count($this->data)>0;
236
			$this->params['hasResponse'] = true;
237
			$this->params['data'] = $this->data;
238
			$this->params['edit'] = $this->createDynamicEditable();
239
			$this->params['meta'] = $this->meta;
240
241
			// createTemplate is an expensive call so only call it once per file and reset all variables on the stored template.
242
			if (!isset($templates[$file]))
243
				$templates[$file] = $this->renderer->createTemplate($file);
244
			$tpl = $templates[$file];
245
			$tpl->tpl_vars = $tpl->config_vars = [];
246
247
			// assign new variables and store results
248
			$tpl->assign($this->params);
249
			$out = $tpl->fetch();
250
			return $out;
251
		}
252
	}
253
254
	/**
255
	 * Get the data request for the widget.
256
	 * Override this if you have a different way of defining your data request
257
	 * @return array
258
	 */
259
	protected function getDataRequest()
260
	{
261
		if (isset($this->params['data']))
262
			return Daedalus::convertDataRequestToJson($this->params['data']);
263
		return null;
264
	}
265
266
	/**
267
	 * Save the data for the widget. Override this if you need to do something
268
	 * else with the data than provided here
269
	 * @param array $data
270
	 */
271
	protected function saveData($data)
272
	{
273
		$this->data = $data;
274
	}
275
276
	/**
277
	 * save any metainformation about the data
278
	 * @param array $meta
279
	 */
280
	private function saveDataMetaInformation($meta)
281
	{
282
		$this->meta = $meta;
283
	}
284
285
	/**
286
	 * @var string the unique id for the widget
287
	 */
288
	private $_id;
289
290
	public static $autoIdPrefix = 'cobe_widget_';
291
292
	public static $counter = 1;
293
294
	/**
295
	 * Get a unique id representing this widget
296
	 * @return string
297
	 */
298
	public function getId()
299
	{
300
		if ($this->_id === null) {
301
			$this->_id = $this->getPage()->getId() . '_' . static::$autoIdPrefix . static::$counter++;
302
		}
303
		return $this->_id;
304
	}
305
306
	/**
307
	 * Create a data request from type and key paramters
308
	 * This is suitable for requests of static or page specific static content
309
	 * @param array &$params  the set of params including
310
	 *   'type' - required - the widget type
311
	 *   'key' - required - an additional key for the data
312
	 *   'page' - optional - if set will include current page in key
313
	 *   'content' - optional - if set, the default content
314
	 *   This will have a 'data' key added created from the above
315
	 */
316
	protected static function buildDataFromCmsKeyAttributes(&$params)
317
	{
318
		if (!isset($params['type'], $params['key']))
319
			return;
320
		$key = "$params[type]_$params[key]";
321
		$pageId = isset($params['page']) ? self::$page->getId() : null;
322
		$params['data-key'] = $key;
323
		$params['data-page-id'] = $pageId;
324
		$params['data'] = "'key':'$key','pageId':'$pageId'";
325
		if (!isset($params['content']))
326
			$params['content'] = "Add Content for $params[key] here";
327
		$params['is_static'] = true;
328
	}
329
330
	/**
331
	 * Create static editable data from a database key and value
332
	 *
333
	 * @param string $key  the static content editable type
334
	 * @param string $value  the value to be displayed
335
	 * @return string  the editable version of the data
336
	 */
337
	protected function createStaticEditable($value)
338
	{
339
		if ($this->getPage()->isInEditMode()) {
340
			$dataKey = $this->params['data-key'];
341
			$dataPageId = $this->params['data-page-id'];
342
			if ((isset($this->params['wys']) || isset($this->params['wysiwyg'])) || (isset($this->params['editor']) && strpos('wys', $this->params['editor'] === 0)))
0 ignored issues
show
Bug introduced by
$this->params['editor'] === 0 of type boolean is incompatible with the type string expected by parameter $needle of strpos(). ( Ignorable by Annotation )

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

342
			if ((isset($this->params['wys']) || isset($this->params['wysiwyg'])) || (isset($this->params['editor']) && strpos('wys', /** @scrutinizer ignore-type */ $this->params['editor'] === 0)))
Loading history...
343
				return '<div id="'.$this->getId().'" data-id="'.$this->getId().'" data-key="'.$dataKey.'" data-page-id="'.$dataPageId.'" class="cobe-editable cobe-static-block" contenteditable="true">' . $value . '</div>';
344
			else
345
				return "<div style='display:inline-block;' class='cobe-editable cobe-static'  data-key='$dataKey' data-page-id='$dataPageId' contenteditable='true' />$value</div>";
346
		} else {
347
			return $value;
348
		}
349
	}
350
351
	/**
352
	 * Create the editable data ($edit) array for use in
353
	 * inline editable areas. This must be identical to $this->data if
354
	 * the page is not being edited, or allow inline editing if the page is being
355
	 * edited. If you override this make sure that is true.
356
	 * @return & array  a reference to the array of $edit
0 ignored issues
show
Documentation Bug introduced by
The doc comment & at position 0 could not be parsed: Unknown type name '&' at position 0 in &.
Loading history...
357
	 */
358
	protected function & createDynamicEditable()
359
	{
360
		return Daedalus::createEditable($this->data);
0 ignored issues
show
Deprecated Code introduced by
The function neon\cms\components\Daedalus::createEditable() has been deprecated. ( Ignorable by Annotation )

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

360
		return /** @scrutinizer ignore-deprecated */ Daedalus::createEditable($this->data);
Loading history...
361
	}
362
}
363