PluginProbe
Depicter — Popup & Slider Builder / 1.2.0
Depicter — Popup & Slider Builder v1.2.0
4.8.1 trunk 1.0.0 1.1.0 1.1.2 1.1.4 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.3.0 1.3.1 1.3.2 1.3.3 1.3.5 1.3.8 1.5.0 1.5.1 1.5.2 1.5.5 1.6.0 1.6.1 1.6.2 1.7.0 All 76 releases
depicter / app / src / Document / Models / Document.php

Document.php in Depicter — Popup & Slider Builder 1.2.0, at app/src/Document/Models/Document.php

600 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Depicter\Document\Models;
3
4
5 use Averta\Core\Hydrate\HydratableInterface;
6 use Averta\Core\Utility\Arr;
7 use Averta\WordPress\Utility\Sanitize;
8 use Depicter\Document\CSS\Selector;
9 use Depicter\Document\Models\Options\Loading;
10 use Depicter\Document\Models\Options\Script;
11 use Depicter\Document\Models\Traits\HasDocumentIdTrait;
12 use Depicter\Html\Html;
13 use Depicter\Services\StyleGeneratorService;
14
15 class Document implements HydratableInterface
16 {
17 use HasDocumentIdTrait;
18
19
20 /**
21 * @var array
22 */
23 public $sectionsList;
24
25 /**
26 * @var Section[]
27 */
28 public $sections;
29
30 /**
31 * @var Element[]
32 */
33 public $elements;
34
35 /**
36 * @var array
37 */
38 public $foregroundElements;
39
40 /**
41 * @var array
42 */
43 public $foregroundElementObjects = [];
44
45 /**
46 * @var Options\All
47 */
48 public $options;
49
50 /**
51 * @var array
52 */
53 public $meta;
54
55 /**
56 * Start from which section
57 *
58 * @var int
59 */
60 public $startSection = 0;
61
62 /**
63 * Document markup
64 *
65 * @var string
66 */
67 protected $html;
68
69 /**
70 * Style generator class instance
71 *
72 * @var StyleGeneratorService
73 */
74 protected $styleGenerator;
75
76 /**
77 * Collected styles in a list
78 *
79 * @var array
80 */
81 protected $stylesList = [];
82
83 /**
84 * Collected fonts from belonging elements
85 *
86 * @var array
87 */
88 private $fontsList = [];
89
90 /**
91 * Link to download all used fonts in this document
92 *
93 * @var string|null
94 */
95 private $fontLink;
96
97 /**
98 * Extract values for this class
99 *
100 * @return array
101 */
102 public function getProperties()
103 {
104 return [
105 'name' => $this->getName(),
106 'slug' => $this->getSlug(),
107 'sections_count' => $this->getSectionsCount(),
108 'content' => $this->get(),
109 'status' => 'published'
110 ];
111 }
112
113 /**
114 * Extract values for this class
115 *
116 * @return array
117 */
118 public function extract()
119 {
120 // TODO: Implement extract() method.
121 }
122
123 /**
124 * Hydrate the class with the provided $data.
125 *
126 * @param array|object $data
127 */
128 public function hydrate($data)
129 {
130 // TODO: Implement hydrate() method.
131 }
132
133 /**
134 * Prepare document for generating markup
135 *
136 * @return $this
137 */
138 public function prepare()
139 {
140 $this->reorderSections();
141 $this->setElementsForObjects();
142 $this->setForegroundElementObjects();
143
144 return $this;
145 }
146
147 public function render()
148 {
149 $this->html = Html::div([
150 'id' => $this->getCssId(),
151 'class' => $this->getClassNames()
152 ]);
153
154 $this->renderLoadingSymbol();
155 $this->renderForegroundElements();
156 $this->renderSectionsAndElements();
157 $this->collectAndSetFontsData();
158 $this->getSelectorAndCssList();
159 $this->renderSymbols();
160
161 return $this->html . $this->getInitScriptTag();
162 }
163
164 /**
165 * Render markup for loading symbols
166 */
167 protected function renderLoadingSymbol() {
168 if ( empty( $this->options->loading ) ) {
169 $this->options->loading = new Loading();
170 }
171 $this->html->nest( "\n" . $this->options->loading->render() );
172 }
173
174 /**
175 * Render symbols markup
176 */
177 protected function renderSymbols() {
178 $symbolsContent = \Depicter::symbolsProvider()->render();
179 if ( !empty( $symbolsContent ) ) {
180 $this->html->nest( "\n" . $symbolsContent );
181 }
182 }
183
184 /**
185 * Render markup and collect styles of foreground elements.
186 */
187 protected function renderForegroundElements(){
188
189 $foregroundAttributes = [ 'class' => Selector::prefixify('overlay-layers') ];
190 $elementsMarkup = "";
191
192 foreach ( $this->foregroundElementObjects as $element ) {
193 $this->stylesList = array_merge( $this->stylesList, $element->prepare()->getSelectorAndCssList() );
194 $elementsMarkup .= $element->prepare()->render() . "\n";
195 }
196
197 if( $elementsMarkup ){
198 $foregroundDiv = Html::div( $foregroundAttributes, "\n" . $elementsMarkup );
199 $this->html->nest( "\n\n" . $foregroundDiv . "\n" );
200 }
201 }
202
203 /**
204 * Get the font link for loading document fonts
205 *
206 * @return string|null
207 */
208 public function getFontsLink()
209 {
210 if( is_null( $this->fontLink ) ){
211 $this->collectAndSetFontsData();
212 }
213 return $this->fontLink;
214 }
215
216 /**
217 * Render markup and collect styles of sections and nested elements.
218 */
219 protected function renderSectionsAndElements(){
220 foreach ( $this->sections as $section ) {
221 $this->html->nest( $section->render() . "\n" );
222 $this->stylesList = array_merge( $this->stylesList, $section->getCss() );
223 }
224 }
225
226 /**
227 * Collects fonts and generates a link for loading document fonts
228 */
229 protected function collectAndSetFontsData()
230 {
231 foreach ( $this->sections as $section ) {
232 // this method adds element fonts to documentFonts service
233 $section->collectElementFonts();
234 }
235 $this->fontLink = \Depicter::app()->documentFonts()->getFontsLink( $this->getDocumentID() );
236 }
237
238 /**
239 * Render document custom styles
240 */
241 /**
242 * Get list of selector and CSS for section
243 *
244 * @return array
245 */
246 protected function getSelectorAndCssList(){
247 if( ! isset( $this->stylesList[ '.'. $this->getSelector() ] ) ){
248 $this->stylesList[ '.'. $this->getSelector() ] = [];
249 }
250
251 $documentStyles = [
252 '.'. $this->getStyleSelector() => $this->options->getStyles(),
253 '.'. $this->getStyleSelector( true ) . ':not(.depicter-ready)' => $this->options->getBeforeInitStyles(), // styles to prevent FOUC. It should not have depicter-revert class in selector
254 '.'. $this->getStyleSelector() . ' .depicter-layers-wrapper' => $this->options->getLayersWrapperStyles()
255 ];
256 // prepend document styles at the beginning of the styles
257 $this->stylesList = $documentStyles + $this->stylesList;
258
259 $this->stylesList[ '.'. $this->getStyleSelector() ]['customStyle'] = $this->getCustomStyles();
260 }
261
262 /**
263 * Retrieves StyleGeneratorService
264 *
265 * @param bool $args
266 *
267 * @return StyleGeneratorService
268 */
269 public function styleGenerator( $args = [] ){
270 $args = Arr::merge( $args, [
271 'forceRegenerateStyles' => false
272 ]);
273
274 if( ! $this->styleGenerator ){
275 $this->styleGenerator = new StyleGeneratorService( $this->stylesList, $this->getDocumentID(), $args );
276 }
277 if( $args['forceRegenerateStyles'] ){
278 $this->styleGenerator->setStylesList( $this->stylesList );
279 }
280
281 return $this->styleGenerator;
282 }
283
284 /**
285 * Saves generated css in file
286 *
287 * @param bool $forceRegenerateStyles Whether regenerate styles or not
288 */
289 public function saveCss( $forceRegenerateStyles = false ){
290 $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->saveCss( $forceRegenerateStyles = false );
291 }
292
293 /**
294 * Retrieves generated css
295 *
296 * @param bool $forceRegenerateStyles Whether regenerate styles or not
297 *
298 * @return string css styles
299 */
300 public function getCss( $forceRegenerateStyles = false ){
301 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCss( $forceRegenerateStyles = false );
302 }
303
304 /**
305 * Retrieves generated css wrapper in a style tag
306 *
307 * @param bool $forceRegenerateStyles Whether regenerate styles or not
308 *
309 * @return string css styles and style tag
310 */
311 public function getInlineCssTag( $forceRegenerateStyles = false ){
312 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCssAndTag( $forceRegenerateStyles = false );
313 }
314
315 /**
316 * Retrieves custom css file of a document if exists
317 *
318 * @param bool $forceRegenerateStyles Whether regenerate styles or not
319 *
320 * @return bool|string
321 */
322 public function getCssFileUrl( $forceRegenerateStyles = false ){
323 if( $forceRegenerateStyles ){
324 $this->saveCss( $forceRegenerateStyles );
325 }
326 if( $cssFile = $this->styleGenerator()->getCssFileUrl() ){
327 return $cssFile;
328 }
329
330 return false;
331 }
332
333 /**
334 * Generates all CSS classes of document wrapper tag
335 *
336 * @return string
337 */
338 protected function getClassNames() {
339 $classes = [ Selector::PREFIX_NAME, Selector::prefixify( Selector::DOCUMENT_PREFIX ), Selector::prefixify( 'revert' ) ];
340 $classes[] = $this->getSelector();
341
342 if ( $this->options->sectionLayout == 'fullscreen' ) {
343 $classes[] = 'depicter-layout-fullscreen';
344 }
345
346 if ( $this->options->sectionLayout == 'fullwidth' ) {
347 $classes[] = 'depicter-layout-fullwidth';
348 }
349
350 if ( $this->getCustomClassName() ) {
351 $classes[] = $this->getCustomClassName();
352 }
353
354 if ( isset( $this->options->general->visible->default ) && $this->options->general->visible->default === false ) {
355 $classes[] = 'depicter-hide-on-desktop';
356 }
357
358 if ( isset( $this->options->general->visible->tablet ) && $this->options->general->visible->tablet === false ) {
359 $classes[] = 'depicter-hide-on-tablet';
360 }
361
362 if ( isset( $this->options->general->visible->mobile ) && $this->options->general->visible->mobile === false ) {
363 $classes[] = 'depicter-hide-on-mobile';
364 }
365
366 return implode( ' ', $classes );
367 }
368
369 protected function getCssId(){
370 return Selector::getFullSelectorPath( $this->getDocumentID() );
371 }
372
373 /**
374 * Retrieves custom class name of document
375 *
376 * @return string
377 */
378 protected function getCustomClassName(){
379 if ( ! empty( $this->options->advanced->className ) ) {
380 return $this->options->advanced->className;
381 }
382 return '';
383 }
384
385 /**
386 * Retrieves custom styles of document
387 *
388 * @return string
389 */
390 protected function getCustomStyles(){
391 if ( ! empty( $this->options->advanced->customStyle ) ) {
392 $customStyles = $this->options->advanced->customStyle;
393 // replace "selector" with unique selector of document
394 return str_replace('selector', '.'.$this->getStyleSelector(), $customStyles );
395 }
396 return '';
397 }
398
399 /**
400 * Retrieves list of all generated custom css files
401 *
402 * @param array|string $fileKeysToInclude Array of file keys or 'all', '*' to retrieve all
403 *
404 * @return array
405 */
406 public function getCustomCssFiles( $fileKeysToInclude = 'all' )
407 {
408 $documentCustomStyles = [];
409
410 if( in_array( $fileKeysToInclude, ['all', '*']) ){
411 $fileKeysToInclude = ['google-font', 'custom'];
412 }
413
414 if( in_array('google-font', $fileKeysToInclude) && $fontLink = $this->getFontsLink() ){
415 $documentCustomStyles[ "depicter-{$this->getDocumentID()}-google-font" ] = $fontLink;
416 }
417 if( in_array('custom', $fileKeysToInclude) && $customCssFileUrl = $this->getCssFileUrl() ){
418 $documentCustomStyles[ "depicter-{$this->getDocumentID()}-custom" ] = $customCssFileUrl;
419 }
420
421 return $documentCustomStyles;
422 }
423
424 /**
425 * Retrieves unique selector of document
426 *
427 * @return string
428 */
429 public function getSelector(){
430 return Selector::getUniqueSelector( $this->getDocumentID() );
431 }
432
433 /**
434 * Get style selector
435 *
436 * @param bool $excludePrefix Whether to exclude selector prefix or not
437 *
438 * @return string
439 */
440 public function getStyleSelector( $excludePrefix = false ) {
441 return ( $excludePrefix ? '' : Selector::PREFIX_CSS . "." ) . $this->getSelector();
442 }
443
444 /**
445 * Order sections based on sectionsList
446 */
447 protected function reorderSections(){
448 $ordered_sections = [];
449 foreach ( $this->sectionsList as $section_id ) {
450 if( isset( $this->sections[ $section_id ] ) ){
451 $ordered_sections[ $section_id ] = $this->sections[ $section_id ];
452 }
453 }
454 $this->sections = $ordered_sections;
455 }
456
457 /**
458 * Assigns belonging elements of all section
459 * Here Objects can be element or section
460 */
461 protected function setElementsForObjects(){
462 foreach ( $this->sections as $section ){
463 // Assign document ID to all sections
464 $section->setDocumentID( $this->getDocumentID() );
465 $this->setElementsForOneObjects( $section );
466 }
467
468 foreach ( $this->elements as $element ){
469 // Assign document ID to all elements
470 $element->setDocumentID( $this->getDocumentID() );
471 $this->setElementsForOneObjects( $element );
472 }
473 }
474
475 /**
476 * Assigns belonging elements of a section
477 *
478 * @param $object
479 */
480 protected function setElementsForOneObjects( &$object ){
481 if ( $elementIds = $object->getElementIds() ) {
482 $elements = $this->sortElementsByDepth( $elementIds );
483 $object->setElementObjects( $elements );
484 }
485 }
486
487 /**
488 * Assigns belonging elements of a section
489 */
490 protected function setForegroundElementObjects(){
491 if ( $elementIds = $this->foregroundElements ) {
492 $this->foregroundElementObjects = $this->sortElementsByDepth( $elementIds );
493 }
494 }
495
496 /**
497 * Sorts elements by depth
498 *
499 * @param array $elementIds
500 *
501 * @return array|Element[]
502 */
503 protected function sortElementsByDepth( $elementIds ){
504 if( empty( $elementIds ) ){
505 return [];
506 }
507
508 $elementsByDepth = [];
509 $elements = [];
510
511 // sort this group of elements in depth
512 foreach ( $elementIds as $elementId ) {
513 $element = $this->elements[ $elementId ];
514 $elementsByDepth[ $element->depth ][] = $element;
515 }
516
517 // sort by ascending depth
518 ksort( $elementsByDepth );
519
520 // collect these elements by depth
521 foreach ( $elementsByDepth as $elementsInADepth ){
522 foreach ( $elementsInADepth as $element ){
523 $elements[] = $element;
524 }
525 }
526
527 return $elements;
528 }
529
530 /**
531 * @return array
532 */
533 public function getMeta()
534 {
535 return $this->meta ?? [];
536 }
537
538 /**
539 * @return Options
540 */
541 public function getOptions()
542 {
543 return $this->options ?? [];
544 }
545
546 /**
547 * Get teh name of document
548 *
549 * @return string
550 */
551 public function getName()
552 {
553 return isset( $this->meta['name'] ) ? $this->meta['name'] : '';
554 }
555
556 /**
557 * Get document slug
558 *
559 * @return mixed|string
560 */
561 public function getSlug()
562 {
563 return isset( $this->meta['slug'] ) ? $this->meta['slug'] : '';
564 }
565
566 /**
567 * Get sections count
568 *
569 * @return int|void
570 */
571 public function getSectionsCount()
572 {
573 return is_array( $this->sectionsList ) ? count( $this->sectionsList ) : 0;
574 }
575
576 /**
577 * Get init script
578 *
579 * @return string
580 */
581 public function getInitScript() {
582 return (new Script())->getDocumentInitScript( $this );
583 }
584
585 /**
586 * Get init script tag
587 */
588 public function getInitScriptTag() {
589 return "\n" . Html::script( [], $this->getInitScript() );
590 }
591
592 /**
593 * Print init script tag
594 */
595 public function printInitScriptTag() {
596 echo Sanitize::html( $this->getInitScriptTag() );
597 }
598
599 }
600