1 <?php
2 
3 namespace ComboStrap;
4 
5 
6 use Doku_Handler;
7 use Doku_Renderer;
8 
9 
10 /**
11  *
12  * TODO: when level 3 of grid
13  *   https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Masonry_Layout
14  *
15  */
16 class MasonryTag
17 {
18     public const TEASER_COLUMNS_TAG = 'teaser-columns';
19     /**
20      * The Tag constant should be the exact same last name of the class
21      * This is how we recognize a tag in the {@link \ComboStrap\CallStack}
22      */
23     public const MASONRY_TAG = "masonry";
24     public const LOGICAL_TAG = "masonry";
25     /**
26      * The syntax tags
27      */
28     public const CARD_COLUMNS_TAG = "card-columns";
29     /**
30      * Same as commercial
31      * https://isotope.metafizzy.co/
32      *
33      */
34     public const MASONRY_SCRIPT_ID = "masonry";
35 
36 
37     /**
38      * In Bootstrap5, to support card-columns, we need masonry javascript and
39      * a column
40      * We close it as seen here:
41      * https://getbootstrap.com/docs/5.0/examples/masonry/
42      *
43      * The column is open with the function {@link MasonryTag::addColIfBootstrap5AndCardColumns()}
44      * @param Doku_Renderer $renderer
45      * @param $context
46      */
47     public static function endColIfBootstrap5AnCardColumns(Doku_Renderer $renderer, $context)
48     {
49 
50         /**
51          * Bootstrap five does not include masonry
52          * directly, we need to add a column
53          * and we close it here
54          */
55         $bootstrapVersion = Bootstrap::getBootStrapMajorVersion();
56         if ($bootstrapVersion == Bootstrap::BootStrapFiveMajorVersion) {
57             $renderer->doc .= '</div>';
58         }
59 
60     }
61 
62     public static function getSyntaxTags(): array
63     {
64         return array(self::MASONRY_TAG, self::CARD_COLUMNS_TAG, self::TEASER_COLUMNS_TAG);
65     }
66 
67     /**
68      * @param $renderer
69      * @param $context Doku_Renderer
70      *
71      * Bootstrap five does not include masonry
72      * directly, we need to add a column around the children {@link syntax_plugin_combo_card} and
73      * {@link BlockquoteTag}
74      * https://getbootstrap.com/docs/5.0/examples/masonry/
75      *
76      * The column is open with the function {@link syntax_plugin_combo_masonry::endColIfBootstrap5AndCardColumns()}
77      *
78      * TODO: do it programmatically by adding call with {@link \ComboStrap\CallStack}
79      */
80     public static function addColIfBootstrap5AndCardColumns(&$renderer, $context)
81     {
82         $bootstrapVersion = Bootstrap::getBootStrapMajorVersion();
83         if ($bootstrapVersion == Bootstrap::BootStrapFiveMajorVersion && $context == MasonryTag::MASONRY_TAG) {
84             $renderer->doc .= '<div class="col-sm-6 col-lg-4 mb-4">';
85         }
86     }
87 
88     public static function handleExit(Doku_Handler $handler)
89     {
90         /**
91          * When the masonry is used in an iterator, the direct
92          * context is lost
93          */
94         $callStack = CallStack::createFromHandler($handler);
95         $callStack->moveToPreviousCorrespondingOpeningCall();
96         while ($actualCall = $callStack->next()) {
97             if (
98                 in_array($actualCall->getTagName(), [CardTag::CARD_TAG, BlockquoteTag::TAG])
99                 && in_array($actualCall->getState(), [DOKU_LEXER_ENTER, DOKU_LEXER_EXIT])
100             ) {
101                 $actualCall->setContext(MasonryTag::MASONRY_TAG);
102             }
103         }
104 
105     }
106 
107     public static function renderEnterTag(): string
108     {
109         $bootstrapVersion = Bootstrap::getBootStrapMajorVersion();
110         switch ($bootstrapVersion) {
111             case 5:
112                 // No support for 5, we use Bs with their example
113                 // https://getbootstrap.com/docs/5.0/examples/masonry/
114                 // https://masonry.desandro.com/layout.html#responsive-layouts
115                 // https://masonry.desandro.com/extras.html#bootstrap
116                 // https://masonry.desandro.com/#initialize-with-vanilla-javascript
117                 PluginUtility::getSnippetManager()->attachRemoteJavascriptLibrary(
118                     MasonryTag::MASONRY_SCRIPT_ID,
119                     "https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js",
120                     "sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D"
121                 );
122                 PluginUtility::getSnippetManager()->attachJavascriptFromComponentId(MasonryTag::MASONRY_SCRIPT_ID);
123                 $masonryClass = MasonryTag::MASONRY_SCRIPT_ID;
124                 return "<div class=\"row $masonryClass\">";
125             default:
126                 return '<div class="card-columns">' ;
127         }
128     }
129 
130     public static function renderExitHtml(): string
131     {
132         return '</div>';
133     }
134 }
135 
136