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

893 lines 20.7 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\Core\Utility\Data;
8 use Averta\WordPress\Utility\Sanitize;
9 use Depicter\Document\CSS\Selector;
10 use Depicter\Document\Models\Common\Animation;
11 use Depicter\Document\Models\Options\Loading;
12 use Depicter\Document\Models\Options\Script;
13 use Depicter\Document\Models\Traits\DocumentAdminNoticeTrait;
14 use Depicter\Html\Html;
15 use Depicter\Services\StyleGeneratorService;
16
17 class Document implements HydratableInterface
18 {
19 use DocumentAdminNoticeTrait;
20
21
22 /**
23 * @var array
24 */
25 public $sectionsList;
26
27 /**
28 * @var Section[]
29 */
30 public $sections;
31
32 /**
33 * @var Element[]
34 */
35 public $elements;
36
37 /**
38 * @var array
39 */
40 public $foregroundElements;
41
42 /**
43 * @var array
44 */
45 public $foregroundElementObjects = [];
46
47 /**
48 * @var Options\All
49 */
50 public $options;
51
52 /**
53 * @var array
54 */
55 public $meta;
56
57 /**
58 * @var array
59 */
60 public $env = [];
61
62 /**
63 * Start from which section
64 *
65 * @var int
66 */
67 public $startSection = 0;
68
69 /**
70 * Document markup
71 *
72 * @var string
73 */
74 protected $html;
75
76 /**
77 * Style generator class instance
78 *
79 * @var StyleGeneratorService
80 */
81 protected $styleGenerator;
82
83 /**
84 * Collected styles in a list
85 *
86 * @var array
87 */
88 protected $stylesList = [];
89
90 /**
91 * Collected fonts from belonging elements
92 *
93 * @var array
94 */
95 private $fontsList = [];
96
97 /**
98 * Link to download all used fonts in this document
99 *
100 * @var string|null
101 */
102 private $fontLink;
103
104 /**
105 * Extra document args
106 *
107 * @var array
108 */
109 private $args = [];
110
111 /**
112 * Check if document is ai generated or not
113 *
114 * @var boolean
115 */
116 public $isBuildWithAI = false;
117
118 /**
119 * check if document has shortcode element or not
120 *
121 * @var boolean
122 */
123 protected $hasShortcodeElement = false;
124
125
126 /**
127 * list of IDs of Form elements in the slider
128 *
129 * @var array
130 */
131 protected $formIDs = [];
132
133 /**
134 * Show if recaptcha is enabled for this document or not
135 *
136 * @var bool
137 */
138 protected $isRecaptchaEnabled = false;
139
140
141 /**
142 * Extract values for this class
143 *
144 * @return array
145 */
146 public function getProperties()
147 {
148 return [
149 'name' => $this->getName(),
150 'slug' => $this->getSlug(),
151 'sections_count' => $this->getSectionsCount(),
152 'content' => $this->get(),
153 'status' => 'published'
154 ];
155 }
156
157 /**
158 * Extract values for this class
159 *
160 * @return array
161 */
162 public function extract()
163 {
164 // TODO: Implement extract() method.
165 }
166
167 /**
168 * Hydrate the class with the provided $data.
169 *
170 * @param array|object $data
171 */
172 public function hydrate($data)
173 {
174 // TODO: Implement hydrate() method.
175 }
176
177 /**
178 * Prepare document for generating markup
179 *
180 * @return $this
181 */
182 public function prepare()
183 {
184 $this->reorderSections();
185 $this->setElementsForObjects();
186 $this->setForegroundElementObjects();
187
188 return $this;
189 }
190
191 public function render()
192 {
193 $documentAnimationAttrs = [];
194
195 if ( $this->isDisplayExtension() ) {
196 if ( !empty( $this->options->documentTypeOptions->displayOptions->animation ) ) {
197 $documentAnimation = (new \JsonMapper())->map( $this->options->documentTypeOptions->displayOptions->animation, new Animation() );
198 $documentAnimationAttrs = $documentAnimation->getAnimationAttrs();
199 }
200 }
201
202 $this->html = Html::div( Arr::merge([
203 'id' => $this->getCssId(),
204 'class' => $this->getClassNames()
205 ], $documentAnimationAttrs ) );
206
207 $this->renderNotice();
208 $this->renderLoadingSymbol();
209 $this->renderForegroundElements();
210 $this->renderSectionsAndElements();
211 $this->collectAndSetFontsData();
212 $this->getSelectorAndCssList();
213 $this->renderSymbols();
214
215 return $this->html . $this->getInitScriptTag();
216 }
217
218 /**
219 * Check if document is display extensions or not
220 *
221 * @return bool
222 */
223 public function isDisplayExtension(): bool{
224 $displayExtensions = [
225 'popup',
226 'banner-bar'
227 ];
228
229 return in_array( $this->getType(), $displayExtensions );
230 }
231
232 /**
233 * Check if document has teaser or not
234 *
235 * @return boolean
236 */
237 public function hasTeaser(): bool {
238 return !empty( $this->options->documentTypeOptions->teaser->enabled );
239 }
240
241 /**
242 * Render markup for possible notices
243 *
244 * @return void
245 */
246 protected function renderNotice(){
247 $notice = $this->getUnpublishedChangesNotice();
248 $notice .= $this->getExpiredSubscriptionNotice();
249 if ( !empty( $notice ) ) {
250 $style = Html::style([],'
251 .depicter-admin-notices {
252 position:absolute;
253 left: 20px;
254 top: 20px;
255 display: flex;
256 gap:8px;
257 flex-direction: column;
258 z-index: 50;
259 }
260 ');
261 $this->html->nest( "\n" . $style );
262 $markup = Html::div([
263 'class' => 'depicter-admin-notices'
264 ], $notice);
265 $this->html->nest( "\n" . $markup );
266 }
267 }
268
269 /**
270 * Render markup for loading symbols
271 */
272 protected function renderLoadingSymbol() {
273 if ( empty( $this->options->loading ) ) {
274 $this->options->loading = new Loading();
275 }
276 $this->html->nest( "\n" . $this->options->loading->render() );
277 }
278
279 /**
280 * Render symbols markup
281 */
282 protected function renderSymbols() {
283 $symbolsContent = \Depicter::symbolsProvider()->render();
284 if ( !empty( $symbolsContent ) ) {
285 $this->html->nestAtTop( $symbolsContent, "\n" );
286 }
287 }
288
289 /**
290 * Render markup and collect styles of foreground elements.
291 */
292 protected function renderForegroundElements(){
293
294 $foregroundAttributes = [ 'class' => Selector::prefixify('overlay-layers') ];
295 $elementsMarkup = "";
296
297 // use the first data sheet for the foreground elements which are dataSource elements
298 $dataSheet = $this->getTheDataSourceDataSheet();
299 foreach ( $this->foregroundElementObjects as $element ) {
300 if ( $dataSheet ) {
301 $element->prepare()->setDataSheet( $dataSheet );
302 }
303
304 $this->stylesList = array_merge( $this->stylesList, $element->prepare()->getSelectorAndCssList() );
305 $elementsMarkup .= $element->prepare()->render() . "\n";
306 }
307
308 if( $elementsMarkup ){
309 $foregroundDiv = Html::div( $foregroundAttributes, "\n" . $elementsMarkup );
310 $this->html->nest( "\n\n" . $foregroundDiv . "\n" );
311 }
312 }
313
314 /**
315 * Get the font link for loading document fonts
316 *
317 * @return string|null
318 */
319 public function getFontsLink()
320 {
321 if( is_null( $this->fontLink ) ){
322 $this->collectAndSetFontsData();
323 }
324 return $this->fontLink;
325 }
326
327 /**
328 * Render markup and collect styles of sections and nested elements.
329 */
330 protected function renderSectionsAndElements(){
331 foreach ( $this->sections as $section ) {
332 if ( $section->getType() == 'teaser' && ! $this->hasTeaser() ) {
333 continue;
334 }
335 $this->html->nest( $section->render() . "\n" );
336 $this->stylesList = array_merge( $this->stylesList, $section->getCss() );
337
338 if ( $section->hasShortcode() ) {
339 $this->hasShortcodeElement = true;
340 }
341
342 $formIDs = $section->hasForm();
343 if ( $formIDs ) {
344 foreach( $formIDs as $formID ) {
345 $this->formIDs[] = $formID['id'];
346 if ( $formID['captcha'] ) {
347 $this->isRecaptchaEnabled = true;
348 }
349 }
350 }
351 }
352 }
353
354 /**
355 * Collects fonts and generates a link for loading document fonts
356 */
357 protected function collectAndSetFontsData(){
358 if( !empty( $this->env['additionalFonts'] ) ){
359 // convert to array recursively
360 $this->env['additionalFonts'] = Data::cast( $this->env['additionalFonts'], 'array' );
361
362 if( is_array( $this->env['additionalFonts'] ) ){
363 foreach( $this->env['additionalFonts'] as $localFontName => $localFontInfo ){
364 \Depicter::documentFonts()->addLocalFont( $this->getDocumentID(), $localFontName, $localFontInfo['variants'] );
365 }
366 }
367 }
368
369 foreach ( $this->sections as $section ) {
370 // this method adds element fonts to documentFonts service
371 $section->collectElementFonts();
372 }
373 $this->fontLink = \Depicter::documentFonts()->getFontsLink( $this->getDocumentID() );
374 }
375
376 /**
377 * Render document custom styles
378 */
379 /**
380 * Get list of selector and CSS for section
381 *
382 * @return array
383 */
384 protected function getSelectorAndCssList(){
385 if( ! isset( $this->stylesList[ '.'. $this->getSelector() ] ) ){
386 $this->stylesList[ '.'. $this->getSelector() ] = [];
387 }
388
389 $documentStyles = [
390 '.'. $this->getStyleSelector() . ' .depicter-section' => $this->options->getSectionGeneralStyles(),
391 '.'. $this->getStyleSelector() . ' .depicter-layers-wrapper' => $this->options->getLayersWrapperStyles()
392 ];
393 // prepend document styles at the beginning of the styles
394 $this->stylesList = $documentStyles + $this->stylesList;
395 $backdropStyles = $this->options->getBackdropStyles();
396 if ( ! empty( $backdropStyles ) ) {
397 $this->stylesList = [
398 '.' . $this->getDisplayStyleSelector() . ' .depicter-backdrop' => $backdropStyles
399 ] + $this->stylesList;
400 }
401
402 $this->stylesList[ '.'. $this->getStyleSelector() ]['customStyle'] = $this->getCustomStyles();
403
404 // add before init styles separately to style list as well
405 $this->stylesList[ '.'. $this->getStyleSelector() ]['beforeInitStyle'] = [
406 '.'. $this->getStyleSelector() => array_merge_recursive( $this->options->getStyles(), $this->options->getPrimaryContainerStyles() ),
407 '.'. $this->getStyleSelector( true ) . ':not(.depicter-ready)' => $this->options->getBeforeInitStyles(), // styles to prevent FOUC. It should not have depicter-revert class in selector
408 ];
409
410 return $this->stylesList;
411 }
412
413 /**
414 * Retrieves StyleGeneratorService
415 *
416 * @param bool $args
417 *
418 * @return StyleGeneratorService
419 */
420 public function styleGenerator( $args = [] ){
421 $args = Arr::merge( $args, [
422 'forceRegenerateStyles' => false
423 ]);
424
425 if( ! $this->styleGenerator ){
426 $this->styleGenerator = new StyleGeneratorService( $this->stylesList, $this->getDocumentID(), $args );
427 }
428 if( $args['forceRegenerateStyles'] ){
429 $this->styleGenerator->setStylesList( $this->stylesList );
430 }
431
432 return $this->styleGenerator;
433 }
434
435 /**
436 * Saves generated css in file
437 *
438 * @param bool $forceRegenerateStyles Whether regenerate styles or not
439 */
440 public function saveCss( $forceRegenerateStyles = false ){
441 $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->saveCss( $forceRegenerateStyles = false );
442 }
443
444 /**
445 * Retrieves generated css
446 *
447 * @param bool $forceRegenerateStyles Whether regenerate styles or not
448 *
449 * @return string css styles
450 */
451 public function getCss( $forceRegenerateStyles = false ){
452 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCss( $forceRegenerateStyles = false );
453 }
454
455 /**
456 * Retrieves before init CSS
457 *
458 * @param bool $forceRegenerateStyles Whether regenerate before init styles or not
459 *
460 * @return string css styles
461 */
462 public function getBeforeInitCssAndTag( $forceRegenerateStyles = false ){
463 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getBeforeInitCssAndTag( $forceRegenerateStyles = false );
464 }
465
466 /**
467 * Retrieves generated css wrapper in a style tag
468 *
469 * @param bool $forceRegenerateStyles Whether regenerate styles or not
470 *
471 * @return string css styles and style tag
472 */
473 public function getInlineCssTag( $forceRegenerateStyles = false ){
474 return $this->styleGenerator( ['forceRegenerateStyles' => $forceRegenerateStyles] )->getCssAndTag( $forceRegenerateStyles = false );
475 }
476
477 /**
478 * Retrieves custom css file of a document if exists
479 *
480 * @param bool $forceRegenerateStyles Whether regenerate styles or not
481 *
482 * @return bool|string
483 */
484 public function getCssFileUrl( $forceRegenerateStyles = false ){
485 if( $forceRegenerateStyles ){
486 $this->saveCss( $forceRegenerateStyles );
487 }
488 if( $cssFile = $this->styleGenerator()->getCssFileUrl() ){
489 return $cssFile;
490 }
491
492 return false;
493 }
494
495 /**
496 * Generates all CSS classes of document wrapper tag
497 *
498 * @return string
499 */
500 protected function getClassNames() {
501 $classes = [ Selector::PREFIX_NAME, Selector::prefixify( Selector::DOCUMENT_PREFIX ), Selector::prefixify( 'revert' ) ];
502 $classes[] = $this->getSelector();
503
504 if ( $this->options->sectionLayout == 'fullscreen' ) {
505 $classes[] = 'depicter-layout-fullscreen';
506 }
507
508 if ( $this->options->sectionLayout == 'fullwidth' ) {
509 $classes[] = 'depicter-layout-fullwidth';
510 }
511
512 if ( $this->getCustomClassName() ) {
513 $classes[] = $this->getCustomClassName();
514 }
515
516 if ( isset( $this->options->general->visible->default ) && $this->options->general->visible->default === false ) {
517 $classes[] = 'depicter-hide-on-desktop';
518 }
519
520 if ( isset( $this->options->general->visible->tablet ) && $this->options->general->visible->tablet === false ) {
521 $classes[] = 'depicter-hide-on-tablet';
522 }
523
524 if ( isset( $this->options->general->visible->mobile ) && $this->options->general->visible->mobile === false ) {
525 $classes[] = 'depicter-hide-on-mobile';
526 }
527
528 if ( $this->isDisplayExtension() ){
529 $classes[] = 'depicter-with-display';
530 }
531
532 return implode( ' ', $classes );
533 }
534
535 public function getCssId(){
536 return Selector::getFullSelectorPath( $this->getDocumentID() );
537 }
538
539 /**
540 * Retrieves custom class name of document
541 *
542 * @return string
543 */
544 protected function getCustomClassName(){
545 if ( ! empty( $this->options->advanced->className ) ) {
546 return $this->options->advanced->className;
547 }
548 return '';
549 }
550
551 /**
552 * Retrieves custom styles of document
553 *
554 * @return string
555 */
556 protected function getCustomStyles(){
557 if ( ! empty( $this->options->advanced->customStyle ) ) {
558 $customStyles = $this->options->advanced->customStyle;
559 // replace "selector" with unique selector of document
560 return str_replace('selector', '.'.$this->getStyleSelector(), $customStyles );
561 }
562 return '';
563 }
564
565 /**
566 * Retrieves list of all generated custom css files
567 *
568 * @param array|string $fileKeysToInclude Array of file keys or 'all', '*' to retrieve all
569 *
570 * @return array
571 */
572 public function getCustomCssFiles( $fileKeysToInclude = 'all' ){
573 $documentCustomStyles = [];
574
575 if( is_string( $fileKeysToInclude ) && in_array( $fileKeysToInclude, [ 'all', '*'] ) ){
576 $fileKeysToInclude = ['google-font', 'custom'];
577 }
578
579 if( in_array('google-font', $fileKeysToInclude) && $fontLink = $this->getFontsLink() ){
580 $useGoogleFonts = \Depicter::options()->get('use_google_fonts', 'on');
581
582 if ( $useGoogleFonts === 'save_locally' ) {
583 $downloadedFonts = \Depicter::googleFontsService()->download( $fontLink );
584
585 foreach( $downloadedFonts as $fontSlug => $fontUrl ) {
586 $documentCustomStyles[ \Depicter::googleFontsService()->getCssIdForLocalFont( $this->getDocumentID(), $fontSlug ) ] = $fontUrl;
587 }
588 } elseif( $useGoogleFonts === 'on' ) {
589 $documentCustomStyles[ "depicter-{$this->getDocumentID()}-google-font" ] = $fontLink;
590 }
591 }
592 if( in_array('custom', $fileKeysToInclude) && $customCssFileUrl = $this->getCssFileUrl() ){
593 $documentCustomStyles[ "depicter--{$this->getDocumentID()}-custom" ] = $customCssFileUrl;
594 }
595
596 return $documentCustomStyles;
597 }
598
599 /**
600 * Retrieves unique selector of document
601 *
602 * @return string
603 */
604 public function getSelector(){
605 return Selector::getUniqueSelector( $this->getDocumentID() );
606 }
607
608 /**
609 * Get style selector
610 *
611 * @param bool $excludePrefix Whether to exclude selector prefix or not
612 *
613 * @return string
614 */
615 public function getStyleSelector( $excludePrefix = false ) {
616 return ( $excludePrefix ? '' : Selector::PREFIX_CSS . "." ) . $this->getSelector();
617 }
618
619 /**
620 * Get display style selector
621 *
622 * @return string
623 */
624 public function getDisplayStyleSelector() {
625 return $this->getSelector() . '-display';
626 }
627
628 /**
629 * Order sections based on sectionsList
630 */
631 protected function reorderSections(){
632 $ordered_sections = [];
633 foreach ( $this->sectionsList as $section_id ) {
634 if( isset( $this->sections[ $section_id ] ) ){
635 $ordered_sections[ $section_id ] = $this->sections[ $section_id ];
636 }
637 }
638 $this->sections = $ordered_sections;
639 }
640
641 /**
642 * Assigns belonging elements of all section
643 * Here Objects can be element or section
644 */
645 protected function setElementsForObjects(){
646 $index = 0;
647 foreach ( $this->sections as $section ){
648 // Assign document ID to all sections
649 $section->setDocumentID( $this->getDocumentID() );
650 $section->setDocumentType( $this->getType() );
651 // set index (order) for this section
652 $section->index = $index;
653 $index++;
654 // set elements for this section
655 $this->setElementsForOneObjects( $section );
656 }
657
658 foreach ( $this->elements as $element ){
659 // Assign document ID to all elements
660 $element->setDocumentID( $this->getDocumentID() );
661 $this->setElementsForOneObjects( $element );
662 }
663 }
664
665 /**
666 * Assigns belonging elements of a section
667 *
668 * @param $object
669 */
670 protected function setElementsForOneObjects( &$object ){
671 if ( $elementIds = $object->getElementIds() ) {
672 $elements = $this->sortElementsByDepth( $elementIds );
673 $object->setElementObjects( $elements );
674 }
675 }
676
677 /**
678 * Assigns belonging elements of a section
679 */
680 protected function setForegroundElementObjects(){
681 if ( $elementIds = $this->foregroundElements ) {
682 $this->foregroundElementObjects = $this->sortElementsByDepth( $elementIds );
683 }
684 }
685
686 /**
687 * Sorts elements by depth
688 *
689 * @param array $elementIds
690 *
691 * @return array|Element[]
692 */
693 protected function sortElementsByDepth( $elementIds ){
694 if( empty( $elementIds ) ){
695 return [];
696 }
697
698 $elementsByDepth = [];
699 $elements = [];
700
701 // sort this group of elements in depth
702 foreach ( $elementIds as $elementId ) {
703 $element = $this->elements[ $elementId ];
704 $elementsByDepth[ $element->depth ][] = $element;
705 }
706
707 // sort by ascending depth
708 ksort( $elementsByDepth );
709
710 // collect these elements by depth
711 foreach ( $elementsByDepth as $elementsInADepth ){
712 foreach ( $elementsInADepth as $element ){
713 $elements[] = $element;
714 }
715 }
716
717 return $elements;
718 }
719
720 /**
721 * @return array|object
722 */
723 public function getMeta()
724 {
725 return $this->meta ?? [];
726 }
727
728 /**
729 * @return Options
730 */
731 public function getOptions()
732 {
733 return $this->options ?? [];
734 }
735
736 /**
737 * Get teh name of document
738 *
739 * @return string
740 */
741 public function getName()
742 {
743 return isset( $this->meta['name'] ) ? $this->meta['name'] : '';
744 }
745
746 /**
747 * Get document slug
748 *
749 * @return mixed|string
750 */
751 public function getSlug()
752 {
753 return isset( $this->meta['slug'] ) ? $this->meta['slug'] : '';
754 }
755
756 /**
757 * Get document type
758 *
759 * @return string
760 */
761 public function getType()
762 {
763 return !empty( $this->meta['documentType'] ) ? $this->meta['documentType'] : 'slider';
764 }
765
766 /**
767 * Get sections count
768 *
769 * @return int|void
770 */
771 public function getSectionsCount()
772 {
773 return is_array( $this->sectionsList ) ? count( $this->sectionsList ) : 0;
774 }
775
776 /**
777 * Gel list of section objects
778 *
779 * @return Section[]
780 */
781 public function getSections()
782 {
783 return $this->sections ?? [];
784 }
785
786 /**
787 * Get a section object by section ID
788 *
789 * @param string $sectionId The section ID
790 *
791 * @return Section|null
792 */
793 public function getSectionById( $sectionId )
794 {
795 return $this->sections[ $sectionId ] ?? null;
796 }
797
798 /**
799 * Get a section by section number. starts from 1
800 *
801 * @param int $sectionNumber The section number
802 *
803 * @return Section|null
804 */
805 public function getSectionNth( $sectionNumber )
806 {
807 if( ! $this->getSections() ){
808 return null;
809 }
810
811 $sectionIndex = $sectionNumber > 0 ? $sectionNumber - 1 : 1;
812 return array_values( $this->getSections() )[ $sectionIndex ] ?? null;
813 }
814
815 /**
816 * Get init script
817 *
818 * @return string
819 */
820 public function getInitScript() {
821 return (new Script())->getDocumentInitScript( $this );
822 }
823
824 /**
825 * Get init script tag
826 */
827 public function getInitScriptTag() {
828 return "\n" . Html::script( [], $this->getInitScript() );
829 }
830
831 /**
832 * Print init script tag
833 */
834 public function printInitScriptTag() {
835 echo Sanitize::html( $this->getInitScriptTag() );
836 }
837
838 /**
839 * Check if document model has shortcode element or not
840 *
841 * @return boolean
842 */
843 public function hasShortcode() {
844 return $this->hasShortcodeElement;
845 }
846
847 /**
848 * Return form ids used in this document
849 *
850 * @return array
851 */
852 public function getFormIDs(): array{
853 return $this->formIDs;
854 }
855
856 /**
857 * Check if form
858 * @return bool
859 */
860 public function isRecaptchaEnabled(): bool {
861 return $this->isRecaptchaEnabled;
862 }
863
864 /**
865 * Get the first data sheet from a data source
866 *
867 * @return bool|null|array
868 */
869 public function getTheDataSourceDataSheet() {
870 $dataSheet = false;
871 foreach( $this->sections as $section ) {
872 if ( $section->dataSource ) {
873 $dataSourceInstance = \Depicter::dataSource()->getByType( $section->dataSource->type );
874 if( $dataSourceInstance ){
875 $dataSheets = $dataSourceInstance->getDataSheetArgs( $section->dataSource->params );
876 foreach( $dataSheets as $dataSheet ){
877 $section->setDataSheet( $dataSheet );
878 break;
879 }
880 $dataSheet = $section->getDataSheet();
881 }
882 }
883
884 if ( $dataSheet ) {
885 break;
886 }
887 }
888
889 return $dataSheet;
890 }
891
892 }
893