PluginProbe
Depicter — Popup & Slider Builder / 1.3.3
Depicter — Popup & Slider Builder v1.3.3
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.3.3, at app/src/Document/Models/Document.php

601 lines 13.8 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() . ' .depicter-section' => $this->options->getSectionGeneralStyles(),
254 '.'. $this->getStyleSelector( true ) . ':not(.depicter-ready)' => $this->options->getBeforeInitStyles(), // styles to prevent FOUC. It should not have depicter-revert class in selector
255 '.'. $this->getStyleSelector() . ' .depicter-layers-wrapper' => $this->options->getLayersWrapperStyles()
256 ];
257 // prepend document styles at the beginning of the styles
258 $this->stylesList = $documentStyles + $this->stylesList;
259
260 $this->stylesList[ '.'. $this->getStyleSelector() ]['customStyle'] = $this->getCustomStyles();
261 }
262
263 /**
264 * Retrieves StyleGeneratorService
265 *
266 * @param bool $args
267 *
268 * @return StyleGeneratorService
269 */
270 public function styleGenerator( $args = [] ){
271 $args = Arr::merge( $args, [
272 'forceRegenerateStyles' => false
273 ]);
274
275 if( ! $this->styleGenerator ){
276 $this->styleGenerator = new StyleGeneratorService( $this->stylesList, $this->getDocumentID(), $args );
277 }
278 if( $args['forceRegenerateStyles'] ){
279 $this->styleGenerator->setStylesList( $this->stylesList );
280 }
281
282 return $this->styleGenerator;
283 }
284
285 /**
286 * Saves generated css in file
287 *
288 * @param bool $forceRegenerateStyles Whether regenerate styles or not
289 */
290 public function saveCss( $forceRegenerateStyles = false ){
291 $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->saveCss( $forceRegenerateStyles = false );
292 }
293
294 /**
295 * Retrieves generated css
296 *
297 * @param bool $forceRegenerateStyles Whether regenerate styles or not
298 *
299 * @return string css styles
300 */
301 public function getCss( $forceRegenerateStyles = false ){
302 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCss( $forceRegenerateStyles = false );
303 }
304
305 /**
306 * Retrieves generated css wrapper in a style tag
307 *
308 * @param bool $forceRegenerateStyles Whether regenerate styles or not
309 *
310 * @return string css styles and style tag
311 */
312 public function getInlineCssTag( $forceRegenerateStyles = false ){
313 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCssAndTag( $forceRegenerateStyles = false );
314 }
315
316 /**
317 * Retrieves custom css file of a document if exists
318 *
319 * @param bool $forceRegenerateStyles Whether regenerate styles or not
320 *
321 * @return bool|string
322 */
323 public function getCssFileUrl( $forceRegenerateStyles = false ){
324 if( $forceRegenerateStyles ){
325 $this->saveCss( $forceRegenerateStyles );
326 }
327 if( $cssFile = $this->styleGenerator()->getCssFileUrl() ){
328 return $cssFile;
329 }
330
331 return false;
332 }
333
334 /**
335 * Generates all CSS classes of document wrapper tag
336 *
337 * @return string
338 */
339 protected function getClassNames() {
340 $classes = [ Selector::PREFIX_NAME, Selector::prefixify( Selector::DOCUMENT_PREFIX ), Selector::prefixify( 'revert' ) ];
341 $classes[] = $this->getSelector();
342
343 if ( $this->options->sectionLayout == 'fullscreen' ) {
344 $classes[] = 'depicter-layout-fullscreen';
345 }
346
347 if ( $this->options->sectionLayout == 'fullwidth' ) {
348 $classes[] = 'depicter-layout-fullwidth';
349 }
350
351 if ( $this->getCustomClassName() ) {
352 $classes[] = $this->getCustomClassName();
353 }
354
355 if ( isset( $this->options->general->visible->default ) && $this->options->general->visible->default === false ) {
356 $classes[] = 'depicter-hide-on-desktop';
357 }
358
359 if ( isset( $this->options->general->visible->tablet ) && $this->options->general->visible->tablet === false ) {
360 $classes[] = 'depicter-hide-on-tablet';
361 }
362
363 if ( isset( $this->options->general->visible->mobile ) && $this->options->general->visible->mobile === false ) {
364 $classes[] = 'depicter-hide-on-mobile';
365 }
366
367 return implode( ' ', $classes );
368 }
369
370 protected function getCssId(){
371 return Selector::getFullSelectorPath( $this->getDocumentID() );
372 }
373
374 /**
375 * Retrieves custom class name of document
376 *
377 * @return string
378 */
379 protected function getCustomClassName(){
380 if ( ! empty( $this->options->advanced->className ) ) {
381 return $this->options->advanced->className;
382 }
383 return '';
384 }
385
386 /**
387 * Retrieves custom styles of document
388 *
389 * @return string
390 */
391 protected function getCustomStyles(){
392 if ( ! empty( $this->options->advanced->customStyle ) ) {
393 $customStyles = $this->options->advanced->customStyle;
394 // replace "selector" with unique selector of document
395 return str_replace('selector', '.'.$this->getStyleSelector(), $customStyles );
396 }
397 return '';
398 }
399
400 /**
401 * Retrieves list of all generated custom css files
402 *
403 * @param array|string $fileKeysToInclude Array of file keys or 'all', '*' to retrieve all
404 *
405 * @return array
406 */
407 public function getCustomCssFiles( $fileKeysToInclude = 'all' )
408 {
409 $documentCustomStyles = [];
410
411 if( is_string( $fileKeysToInclude ) && in_array( $fileKeysToInclude, [ 'all', '*'] ) ){
412 $fileKeysToInclude = ['google-font', 'custom'];
413 }
414
415 if( in_array('google-font', $fileKeysToInclude) && $fontLink = $this->getFontsLink() ){
416 $documentCustomStyles[ "depicter-{$this->getDocumentID()}-google-font" ] = $fontLink;
417 }
418 if( in_array('custom', $fileKeysToInclude) && $customCssFileUrl = $this->getCssFileUrl() ){
419 $documentCustomStyles[ "depicter-{$this->getDocumentID()}-custom" ] = $customCssFileUrl;
420 }
421
422 return $documentCustomStyles;
423 }
424
425 /**
426 * Retrieves unique selector of document
427 *
428 * @return string
429 */
430 public function getSelector(){
431 return Selector::getUniqueSelector( $this->getDocumentID() );
432 }
433
434 /**
435 * Get style selector
436 *
437 * @param bool $excludePrefix Whether to exclude selector prefix or not
438 *
439 * @return string
440 */
441 public function getStyleSelector( $excludePrefix = false ) {
442 return ( $excludePrefix ? '' : Selector::PREFIX_CSS . "." ) . $this->getSelector();
443 }
444
445 /**
446 * Order sections based on sectionsList
447 */
448 protected function reorderSections(){
449 $ordered_sections = [];
450 foreach ( $this->sectionsList as $section_id ) {
451 if( isset( $this->sections[ $section_id ] ) ){
452 $ordered_sections[ $section_id ] = $this->sections[ $section_id ];
453 }
454 }
455 $this->sections = $ordered_sections;
456 }
457
458 /**
459 * Assigns belonging elements of all section
460 * Here Objects can be element or section
461 */
462 protected function setElementsForObjects(){
463 foreach ( $this->sections as $section ){
464 // Assign document ID to all sections
465 $section->setDocumentID( $this->getDocumentID() );
466 $this->setElementsForOneObjects( $section );
467 }
468
469 foreach ( $this->elements as $element ){
470 // Assign document ID to all elements
471 $element->setDocumentID( $this->getDocumentID() );
472 $this->setElementsForOneObjects( $element );
473 }
474 }
475
476 /**
477 * Assigns belonging elements of a section
478 *
479 * @param $object
480 */
481 protected function setElementsForOneObjects( &$object ){
482 if ( $elementIds = $object->getElementIds() ) {
483 $elements = $this->sortElementsByDepth( $elementIds );
484 $object->setElementObjects( $elements );
485 }
486 }
487
488 /**
489 * Assigns belonging elements of a section
490 */
491 protected function setForegroundElementObjects(){
492 if ( $elementIds = $this->foregroundElements ) {
493 $this->foregroundElementObjects = $this->sortElementsByDepth( $elementIds );
494 }
495 }
496
497 /**
498 * Sorts elements by depth
499 *
500 * @param array $elementIds
501 *
502 * @return array|Element[]
503 */
504 protected function sortElementsByDepth( $elementIds ){
505 if( empty( $elementIds ) ){
506 return [];
507 }
508
509 $elementsByDepth = [];
510 $elements = [];
511
512 // sort this group of elements in depth
513 foreach ( $elementIds as $elementId ) {
514 $element = $this->elements[ $elementId ];
515 $elementsByDepth[ $element->depth ][] = $element;
516 }
517
518 // sort by ascending depth
519 ksort( $elementsByDepth );
520
521 // collect these elements by depth
522 foreach ( $elementsByDepth as $elementsInADepth ){
523 foreach ( $elementsInADepth as $element ){
524 $elements[] = $element;
525 }
526 }
527
528 return $elements;
529 }
530
531 /**
532 * @return array
533 */
534 public function getMeta()
535 {
536 return $this->meta ?? [];
537 }
538
539 /**
540 * @return Options
541 */
542 public function getOptions()
543 {
544 return $this->options ?? [];
545 }
546
547 /**
548 * Get teh name of document
549 *
550 * @return string
551 */
552 public function getName()
553 {
554 return isset( $this->meta['name'] ) ? $this->meta['name'] : '';
555 }
556
557 /**
558 * Get document slug
559 *
560 * @return mixed|string
561 */
562 public function getSlug()
563 {
564 return isset( $this->meta['slug'] ) ? $this->meta['slug'] : '';
565 }
566
567 /**
568 * Get sections count
569 *
570 * @return int|void
571 */
572 public function getSectionsCount()
573 {
574 return is_array( $this->sectionsList ) ? count( $this->sectionsList ) : 0;
575 }
576
577 /**
578 * Get init script
579 *
580 * @return string
581 */
582 public function getInitScript() {
583 return (new Script())->getDocumentInitScript( $this );
584 }
585
586 /**
587 * Get init script tag
588 */
589 public function getInitScriptTag() {
590 return "\n" . Html::script( [], $this->getInitScript() );
591 }
592
593 /**
594 * Print init script tag
595 */
596 public function printInitScriptTag() {
597 echo Sanitize::html( $this->getInitScriptTag() );
598 }
599
600 }
601