PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.3
Tutor LMS – eLearning and online course solution v4.0.3
4.0.3 4.0.2 4.0.1 4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / components / Accordion.php
tutor / components Last commit date
Constants 3 weeks ago Accordion.php 6 days ago Alert.php 6 days ago AttachmentCard.php 6 days ago Avatar.php 6 days ago Badge.php 6 days ago BaseComponent.php 3 weeks ago Button.php 6 days ago ConfirmationModal.php 6 days ago CourseFilter.php 6 days ago DateFilter.php 6 days ago DropdownFilter.php 6 days ago EmptyState.php 6 days ago FileUploader.php 6 days ago InputField.php 6 days ago Modal.php 6 days ago Nav.php 6 days ago Pagination.php 6 days ago Popover.php 6 days ago PreviewTrigger.php 6 days ago Progress.php 6 days ago SearchFilter.php 6 days ago Sorting.php 6 days ago StarRating.php 6 days ago StarRatingInput.php 6 days ago StatusSelect.php 6 days ago SvgIcon.php 6 days ago Table.php 6 days ago Tabs.php 6 days ago Tooltip.php 6 days ago WPEditor.php 6 days ago
Accordion.php
293 lines
1 <?php
2 /**
3 * Tutor Component: Accordion
4 *
5 * Provides a fluent builder for rendering accordion items with
6 * Alpine.js integration for expand/collapse functionality.
7 *
8 * @package Tutor\Components
9 * @author Themeum
10 * @link https://themeum.com
11 * @since 4.0.0
12 */
13
14 namespace Tutor\Components;
15
16 use TUTOR\Icon;
17
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * Accordion Component Class.
22 *
23 * Example usage:
24 * ```
25 * // Single item accordion
26 * Accordion::make()
27 * ->add_item( 'About Course', '<p>Description...</p>' )
28 * ->render();
29 *
30 * // Multiple items, first open by default
31 * Accordion::make()
32 * ->add_item( 'About Course', '<p>Description...</p>' )
33 * ->add_item( 'Requirements', '<p>Prerequisites...</p>' )
34 * ->add_item( 'Instructor', '<p>Meet your instructor...</p>' )
35 * ->default_open( array( 0 ) )
36 * ->render();
37 *
38 * // Multiple items open by default (indices 0 and 2)
39 * Accordion::make()
40 * ->add_item( 'Overview', '<p>Course overview...</p>' )
41 * ->add_item( 'Curriculum', '<p>Topics covered...</p>' )
42 * ->add_item( 'FAQ', '<p>Common questions...</p>' )
43 * ->default_open( array( 0, 2 ) )
44 * ->render();
45 *
46 * // Only one item open at a time (allow_multiple = false)
47 * Accordion::make()
48 * ->add_item( 'Section 1', '<p>Content 1...</p>' )
49 * ->add_item( 'Section 2', '<p>Content 2...</p>' )
50 * ->allow_multiple( false )
51 * ->render();
52 *
53 * // With custom icon per item
54 * Accordion::make()
55 * ->add_item( 'Resources', '', '', Icon::RESOURCES )
56 * ->add_item( 'Downloads', '', '', Icon::DOWNLOAD_2 )
57 * ->render();
58 *
59 * // With a PHP template file as content
60 * Accordion::make()
61 * ->add_item( 'Details', '', get_template_directory() . '/partials/details.php' )
62 * ->render();
63 *
64 * // Extra HTML attributes on the wrapper
65 * Accordion::make()
66 * ->add_item( 'Notes', '<p>Some notes...</p>' )
67 * ->attr( 'id', 'course-accordion' )
68 * ->attr( 'class', 'my-custom-class' )
69 * ->render();
70 * ```
71 *
72 * @since 4.0.0
73 */
74 class Accordion extends BaseComponent {
75
76 /**
77 * Accordion items array.
78 *
79 * @since 4.0.0
80 *
81 * @var array
82 */
83 protected $items = array();
84
85 /**
86 * Whether multiple items can be open.
87 *
88 * @since 4.0.0
89 *
90 * @var bool
91 */
92 protected $multiple = true;
93
94 /**
95 * Default open item indices.
96 *
97 * @since 4.0.0
98 *
99 * @var array
100 */
101 protected $default_open = array();
102
103 /**
104 * Add accordion item.
105 *
106 * @since 4.0.0
107 *
108 * @param string $title Item title.
109 * @param string $content Item content HTML.
110 * @param string $template Optional. Template path instead of content.
111 * @param string $icon Optional. Custom icon name.
112 *
113 * @return $this
114 */
115 public function add_item( $title, $content = '', $template = '', $icon = '' ) {
116 $this->items[] = array(
117 'title' => $title,
118 'content' => $content,
119 'template' => $template,
120 'icon' => $icon,
121 );
122 return $this;
123 }
124
125 /**
126 * Set whether multiple items can be open.
127 *
128 * @since 4.0.0
129 *
130 * @param bool $multiple Whether to allow multiple open items.
131 *
132 * @return $this
133 */
134 public function allow_multiple( $multiple = true ) {
135 $this->multiple = (bool) $multiple;
136 return $this;
137 }
138
139 /**
140 * Set default open item indices.
141 *
142 * @since 4.0.0
143 *
144 * @param array $indices Array of item indices to open by default.
145 *
146 * @return $this
147 */
148 public function default_open( $indices ) {
149 $this->default_open = is_array( $indices ) ? $indices : array( $indices );
150 return $this;
151 }
152
153 /**
154 * Render accordion item content.
155 *
156 * @since 4.0.0
157 *
158 * @param array $item Item data.
159 *
160 * @return string Content HTML.
161 */
162 protected function render_item_content( $item ) {
163 // If template is provided, use it.
164 if ( ! empty( $item['template'] ) && file_exists( $item['template'] ) ) {
165 ob_start();
166 include $item['template'];
167 return ob_get_clean();
168 }
169
170 // Otherwise return content.
171 return ! empty( $item['content'] ) ? $item['content'] : '';
172 }
173
174 /**
175 * Render default chevron icon.
176 *
177 * @since 4.0.0
178 *
179 * @return string Icon SVG.
180 */
181 protected function render_default_icon() {
182 return SvgIcon::make()->name( Icon::CHEVRON_DOWN )->size( 24 )->get();
183 }
184
185 /**
186 * Render custom icon.
187 *
188 * @since 4.0.0
189 *
190 * @param string $icon Icon name.
191 *
192 * @return string Icon SVG.
193 */
194 protected function render_icon( $icon ) {
195 if ( empty( $icon ) ) {
196 return $this->render_default_icon();
197 }
198
199 return SvgIcon::make()->name( $icon )->size( 24 )->get();
200 }
201
202 /**
203 * Get the accordion HTML.
204 *
205 * @since 4.0.0
206 *
207 * @return string HTML output.
208 */
209 public function get(): string {
210 if ( empty( $this->items ) ) {
211 return '';
212 }
213
214 // Build Alpine.js config.
215 $alpine_config = array(
216 'multiple' => $this->multiple,
217 'defaultOpen' => $this->default_open,
218 );
219 $alpine_json = wp_json_encode( $alpine_config );
220
221 // Merge custom classes.
222 $wrapper_classes = 'tutor-accordion';
223 if ( ! empty( $this->attributes['class'] ) ) {
224 $wrapper_classes .= ' ' . $this->attributes['class'];
225 unset( $this->attributes['class'] );
226 }
227
228 $this->attributes['x-data'] = sprintf( 'tutorAccordion(%s)', $alpine_json );
229 $this->attributes['class'] = $wrapper_classes;
230
231 $wrapper_attrs = $this->get_attributes_string();
232
233 // Build items HTML.
234 $items_html = '';
235 foreach ( $this->items as $index => $item ) {
236 $title = isset( $item['title'] ) ? $item['title'] : '';
237 $icon = isset( $item['icon'] ) ? $item['icon'] : '';
238 $panel_id = 'tutor-acc-panel-' . $index;
239 $trigger_id = 'tutor-acc-trigger-' . $index;
240
241 $icon_html = $this->render_icon( $icon );
242 $content = $this->render_item_content( $item );
243
244 $items_html .= sprintf(
245 '<div class="tutor-accordion-item">
246 <button
247 @click="toggle(%d)"
248 @keydown="handleKeydown($event, %d)"
249 :aria-expanded="isOpen(%d)"
250 class="tutor-accordion-header tutor-accordion-trigger"
251 aria-controls="%s"
252 id="%s"
253 >
254 <span class="tutor-accordion-title">%s</span>
255 <span class="tutor-accordion-icon" aria-hidden="true">
256 %s
257 </span>
258 </button>
259 <div
260 id="%s"
261 role="region"
262 aria-labelledby="%s"
263 class="tutor-accordion-content"
264 x-show="isOpen(%d)"
265 x-collapse.duration.350ms
266 >
267 <div class="tutor-accordion-body">
268 %s
269 </div>
270 </div>
271 </div>',
272 $index,
273 $index,
274 $index,
275 esc_attr( $panel_id ),
276 esc_attr( $trigger_id ),
277 esc_html( $title ),
278 $icon_html,
279 esc_attr( $panel_id ),
280 esc_attr( $trigger_id ),
281 $index,
282 wp_kses_post( $content )
283 );
284 }
285
286 return sprintf(
287 '<div %s>%s</div>',
288 $wrapper_attrs,
289 $items_html
290 );
291 }
292 }
293