Passed
Branch dev (72fba1)
by Michael
05:23
created

___addClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 3
dl 0
loc 4
rs 10
c 2
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
/**
3
 * Admin Page Framework
4
 *
5
 * http://admin-page-framework.michaeluno.jp/
6
 * Copyright (c) 2013-2021, Michael Uno; Licensed MIT
7
 *
8
 */
9
10
/**
11
 * Provides utility methods which do not use WordPress functions.
12
 *
13
 * @since       3.9.0
14
 * @package     AdminPageFramework/Utility
15
 * @internal
16
 */
17
class AdminPageFramework_Utility_Interpreter extends AdminPageFramework_Utility_HTMLAttribute {
18
19
    /**
20
     * Returns a readable list of the given array contents.
21
     *
22
     * @remark      If the second dimension element is an array, it will be enclosed in parentheses.
23
     * @since       3.3.0
24
     * @since       3.9.0       Moved from `AdminPageFramework_Utility_Array.php`.
25
     * @return      string      A readable list generated from the given array.
26
     */
27
    static public function getReadableListOfArray( array $aArray ) {
28
29
        $_aOutput   = array();
30
        foreach( $aArray as $_sKey => $_vValue ) {
31
            $_aOutput[] = self::getReadableArrayContents( $_sKey, $_vValue, 32 ) . PHP_EOL;
32
        }
33
        return implode( PHP_EOL, $_aOutput );
34
35
    }
36
    /**
37
     * Generates readable array contents.
38
     *
39
     * @since       3.3.0
40
     * @since       3.9.0       Moved from `AdminPageFramework_Utility_Array.php`.
41
     * @return      string      The generated human-readable array contents.
42
     */
43
    static public function getReadableArrayContents( $sKey, $vValue, $sLabelCharLengths=16, $iOffset=0 ) {
44
45
        $_aOutput   = array();
46
        $_aOutput[] = ( $iOffset
47
                ? str_pad( ' ', $iOffset  )
48
                : ''
49
            )
50
            . ( $sKey
51
                ? '[' . $sKey . ']'
52
                : ''
53
            );
54
55
        if ( ! in_array( gettype( $vValue ), array( 'array', 'object' ) ) ) {
56
            $_aOutput[] = $vValue;
57
            return implode( PHP_EOL, $_aOutput );
58
        }
59
60
        foreach ( $vValue as $_sTitle => $_asDescription ) {
61
            if ( ! in_array( gettype( $_asDescription ), array( 'array', 'object' ) ) ) {
62
                $_aOutput[] = str_pad( ' ', $iOffset )
63
                    . $_sTitle
64
                    . str_pad( ':', $sLabelCharLengths - self::getStringLength( $_sTitle ) )
65
                    . $_asDescription;
66
                continue;
67
            }
68
            $_aOutput[] = str_pad( ' ', $iOffset )
69
                . $_sTitle
70
                . ": {"
71
                . self::getReadableArrayContents( '', $_asDescription, 16, $iOffset + 4 )
72
                . PHP_EOL
73
                . str_pad( ' ', $iOffset ) . "}";
74
        }
75
        return implode( PHP_EOL, $_aOutput );
76
77
    }
78
    /**
79
     * Returns the readable list of the given array contents as HTML.
80
     *
81
     * @since       3.3.0
82
     * @since       3.9.0       Moved from `AdminPageFramework_Utility_Array.php`.
83
     * @return      string      The HTML list generated from the given array.
84
     */
85
    static public function getReadableListOfArrayAsHTML( array $aArray ) {
86
        $_aOutput   = array();
87
        foreach( $aArray as $_sKey => $_vValue ) {
88
            $_aOutput[] = "<ul class='array-contents'>"
89
                    .  self::getReadableArrayContentsHTML( $_sKey, $_vValue )
90
                . "</ul>" . PHP_EOL;
91
        }
92
        return implode( PHP_EOL, $_aOutput );
93
    }
94
95
    /**
96
     * Returns the readable array contents.
97
     *
98
     * @since       3.3.0
99
     * @since       3.9.0       Moved from `AdminPageFramework_Utility_Array.php`.
100
     * @return      string      The HTML output generated from the given array.
101
     */
102
    static public function getReadableArrayContentsHTML( $sKey, $vValue ) {
103
104
        // Output container.
105
        $_aOutput   = array();
106
107
        // Title - array key
108
        $_aOutput[] = $sKey
109
            ? "<h3 class='array-key'>" . $sKey . "</h3>"
110
            : "";
111
112
        // If it does not have a nested array or object,
113
        if ( ! in_array( gettype( $vValue ), array( 'array', 'object' ), true ) ) {
114
            $_aOutput[] = "<div class='array-value'>"
115
                    . html_entity_decode( nl2br( $vValue ), ENT_QUOTES )
116
                . "</div>";
117
            return "<li>" . implode( PHP_EOL, $_aOutput ) . "</li>";
118
        }
119
120
        // Now it is a nested item.
121
        foreach ( $vValue as $_sKey => $_vValue ) {
122
            $_aOutput[] =  "<ul class='array-contents'>"
123
                    . self::getReadableArrayContentsHTML( $_sKey, $_vValue )
124
                . "</ul>";
125
        }
126
        return implode( PHP_EOL, $_aOutput ) ;
127
128
    }
129
130
    /**
131
     * Generates an HTML table from a given array.
132
     *
133
     * Similar to `getTableOfArray()` but this does not support multiple columns in a single row.
134
     * All rows consist of key-value pair, representing the array structure.
135
     *
136
     * @param  array   $aArray
137
     * @param  array   $aAllAttributes
138
     * @param  array   $aHeader
139
     * @param  array   $aFooter
140
     * @param  boolean $bEscape
141
     * @param  string  $sCaption
142
     * @return string
143
     * @since  3.9.0
144
     */
145
    static public function getTableOfKeyValues( array $aArray, array $aAllAttributes=array(), array $aHeader=array(), array $aFooter=array(), $bEscape=true, $sCaption='' ) {
146
        $_aAllAttributes = $aAllAttributes + array(
147
            'table'   => array(),
148
            'caption' => array(),
149
            'tbody'   => array(),
150
            'td'      => array(
151
                array(),
152
                array(),
153
            ),
154
            'tr'      => array(),
155
            't'       => array(),
156
            'ul'      => array(),
157
            'li'      => array(),
158
            'p'       => array(),
159
        );
160
        return "<table " . self::getAttributes( self::getElementAsArray( $_aAllAttributes, 'table' ) ) . ">"
161
                . self::___getTableCaption( $sCaption, $_aAllAttributes, $bEscape )
162
                . self::___getTableHeaderOfKeyValuePair( $aHeader, $aAllAttributes, $bEscape )
163
                . "<tbody " . self::getAttributes( self::getElementAsArray( $_aAllAttributes, 'tbody' ) ) . ">"
164
                    . self::___getRowsOfKeyValuePair( $aArray, $aAllAttributes, $bEscape )
165
                . "</tbody>"
166
                . self::___getTableFooterOfKeyValuePair( $aFooter, $aAllAttributes, $bEscape )
167
            . "</table>";
168
    }
169
170
    /**
171
     * Generates a table output of a given array.
172
     * Designed to display key-value pairs in a table.
173
     *
174
     * @param  array   $aArray           The data to display in a table.
175
     * @param  array   $aAllAttributes   A set of array representing tag attributes.
176
     * @param  array   $aHeader          Key value pairs of the table header. Only the first depth is supported.
177
     * @param  array   $aFooter          Key value pairs of the table footer. Only the first depth is supported.
178
     * @param  boolean $bEscape          Whether to escape values or not.
179
     * @param  string  $sCaption         The table caption.
180
     * @return string
181
     * @since  3.9.0
182
     */
183
    static public function getTableOfArray( array $aArray, array $aAllAttributes=array(), array $aHeader=array(), array $aFooter=array(), $bEscape=true, $sCaption='' ) {
184
185
        $_aAllAttributes = $aAllAttributes + array(
186
            'table'   => array(),
187
            'caption' => array(),
188
            'tbody'   => array(),
189
            'td'      => array(
190
                array(),
191
                array(),
192
            ),
193
            'tr'      => array(),
194
            't'       => array(),
195
            'ul'      => array(),
196
            'li'      => array(),
197
            'p'       => array(),
198
        );
199
        return "<table " . self::getAttributes( self::getElementAsArray( $_aAllAttributes, 'table' ) ) . ">"
200
                . self::___getTableCaption( $sCaption, $_aAllAttributes, $bEscape )
201
                . self::___getTableHeader( $aHeader, $_aAllAttributes, $bEscape )
202
                . "<tbody " . self::getAttributes( self::getElementAsArray( $_aAllAttributes, 'tbody' ) ) . ">"
203
                    . self::___getTableRows( $aArray, $_aAllAttributes, $bEscape )
204
                . "</tbody>"
205
                . self::___getTableFooter( $aFooter, $_aAllAttributes, $bEscape )
206
            . "</table>";
207
    }
208
        static private function ___getTableCaption( $sCaption, $aAllAttributes, $bEscape ) {
209
            $sCaption = ( string ) $sCaption;
210
            if ( ! strlen( $sCaption ) ) {
211
                return '';
212
            }
213
            $_aCapAttr = self::getElementAsArray( $aAllAttributes, 'caption' );
214
            $_sCaption = $bEscape
215
                ? htmlspecialchars( $sCaption )
216
                : $sCaption;
217
            return "<caption " . self::getAttributes( $_aCapAttr ) . ">"
218
                    . $_sCaption
219
                . "</caption>";
220
        }
221
        static private function ___getHTMLEscaped( $sOutput, $bEscape ) {
222
            return $bEscape ? htmlspecialchars( $sOutput ) : $sOutput;
223
        }
224
        static private function ___getTableHeader( array $aHeader, array $aAllAttributes, $bEscape ) {
225
            if ( empty( $aHeader ) ) {
226
                return '';
227
            }
228
            return self::isAssociative( $aHeader )
229
                ? self::___getTableHeaderOfKeyValuePair( $aHeader, $aAllAttributes, $bEscape )
230
                : self::___getTableHeaderOfMultiColumns( $aHeader, $aAllAttributes, $bEscape );
231
232
        }
233
            static private function ___getTableHeaderOfKeyValuePair( array $aHeader, array $aAllAttributes, $bEscape ) {
234
                $_aTRAttr  = self::getElementAsArray( $aAllAttributes, 'tr' );
235
                $_aTRAttr[ 'class' ] = self::getClassAttribute( 'key-value', self::getElement( $_aTRAttr, array( 'class' ), '' ) );
236
                $_aTHAttr  = self::getElementAsArray( $aAllAttributes, 'th' );
237
                $_aTHAttr1 = self::getElementAsArray( $aAllAttributes, array( 'th', 0 ) ) + $_aTHAttr;
238
                $_aTHAttr2 = self::getElementAsArray( $aAllAttributes, array( 'th', 1 ) ) + $_aTHAttr;
239
                $_sOutput = '';
240
                foreach( $aHeader as $_sKey => $_sValue ) {
241
                    $_sOutput .= "<tr " . self::getAttributes( $_aTRAttr ) . ">"
242
                            . "<th " . self::getAttributes( $_aTHAttr1 ) . ">" . self::___getHTMLEscaped( $_sKey, $bEscape ) . "</th>"
243
                            . "<th " . self::getAttributes( $_aTHAttr2 ) . ">" . self::___getHTMLEscaped( $_sValue, $bEscape ) . "</th>"
244
                        . "</tr>";
245
                }
246
                return "<thead>" . $_sOutput . "</thead>";
247
            }
248
            static private function ___getTableHeaderOfMultiColumns( array $aHeader, array $aAllAttributes, $bEscape ) {
249
                $_aTRAttr  = self::getElementAsArray( $aAllAttributes, 'tr' );
250
                $_aTHAttr  = self::getElementAsArray( $aAllAttributes, 'th' );
251
                $_sOutput  = "<tr " . self::getAttributes( $_aTRAttr ) . ">";
252
                foreach( array_values( $aHeader ) as $_iIndex => $_sColumnName ) {
253
                    $_aTHAttrNth  = self::getElementAsArray( $aAllAttributes, array( 'th', $_iIndex ) ) + $_aTHAttr;
254
                    $_sOutput    .= "<th " . self::getAttributes( $_aTHAttrNth ) . ">" . self::___getHTMLEscaped( ( string ) $_sColumnName, $bEscape ) . "</th>";
255
                }
256
                $_sOutput .= "</tr>";
257
                return "<thead>" . $_sOutput . "</thead>";
258
            }
259
        static private function ___getTableFooter( array $aFooter, array $aAllAttributes, $bEscape ) {
260
            if ( empty( $aFooter ) ) {
261
                return '';
262
            }
263
            return self::isAssociative( $aFooter )
264
                ? self::___getTableFooterOfKeyValuePair( $aFooter, $aAllAttributes, $bEscape )
265
                : self::___getTableFooterOfMultiColumns( $aFooter, $aAllAttributes, $bEscape );
266
        }
267
            static private function ___getTableFooterOfKeyValuePair( array $aFooter, array $aAllAttributes, $bEscape ) {
268
                $_aTRAttr  = self::getElementAsArray( $aAllAttributes, 'tr' );
269
                $_aTDAttr  = self::getElementAsArray( $aAllAttributes, 'td' );
270
                $_aTRAttr[ 'class' ] = self::getClassAttribute( 'key-value', self::getElement( $_aTRAttr, array( 'class' ), '' ) );
271
                $_aTDAttr1 = self::getElementAsArray( $aAllAttributes, array( 'td', 0 ) ) + $_aTDAttr;
272
                $_aTDAttr2 = self::getElementAsArray( $aAllAttributes, array( 'td', 1 ) ) + $_aTDAttr;
273
                $_sOutput = '';
274
                foreach( $aFooter as $_sKey => $_sValue ) {
275
                    $_sOutput = "<tr " . self::getAttributes( $_aTRAttr ) . ">"
276
                            . "<td " . self::getAttributes( $_aTDAttr1 ) . ">" . self::___getHTMLEscaped( $_sKey, $bEscape ) . "</td>"
277
                            . "<td " . self::getAttributes( $_aTDAttr2 ) . ">" . self::___getHTMLEscaped( $_sValue, $bEscape ) . "</td>"
278
                        . "</tr>";
279
                }
280
                return "<tfoot>" . $_sOutput . "</tfoot>";                
281
            }
282
            static private function ___getTableFooterOfMultiColumns( array $aFooter, array $aAllAttributes, $bEscape ) {
283
                $_aTRAttr  = self::getElementAsArray( $aAllAttributes, 'tr' );
284
                $_aTDAttr  = self::getElementAsArray( $aAllAttributes, 'td' );
285
                $_sOutput  = "<tr " . self::getAttributes( $_aTRAttr ) . ">";
286
                foreach( array_values( $aFooter ) as $_iIndex => $_sColumnName ) {
287
                    $_aTDAttrNth  = self::getElementAsArray( $aAllAttributes, array( 'td', $_iIndex ) ) + $_aTDAttr;
288
                    $_sOutput    .= "<td " . self::getAttributes( $_aTDAttrNth ) . ">" . self::___getHTMLEscaped( ( string ) $_sColumnName, $bEscape ) . "</td>";
289
                }
290
                $_sOutput .= "</tr>";
291
                return "<tfoot>" . $_sOutput . "</tfoot>";
292
            }            
293
        static private function ___getTableRows( array $aArray, array $aAllAttributes, $bEscape ) {
294
            if ( empty( $aArray ) ) {
295
                return '';
296
            }
297
            return self::___shouldKeyValuePair( $aArray )
298
                ? self::___getRowsOfKeyValuePair( $aArray, $aAllAttributes, $bEscape )
299
                : self::___getRowsOfMultiColumns( $aArray, $aAllAttributes, $bEscape );
300
        }
301
            static private function ___shouldKeyValuePair( array $aArray ) {
302
                if ( self::isAssociative( $aArray ) ) {
303
                    return true;
304
                }
305
                $_aFirstItem = self::getAsArray( self::getFirstElement( $aArray ) );
306
                if ( self::isAssociative( $_aFirstItem ) || self::isMultiDimensional( $_aFirstItem ) ) {
307
                    return true;
308
                }
309
                return false;
310
            }
311
312
            /**
313
             * @param  array   $aItem
314
             * @param  array   $aAllAttributes
315
             * @param  boolean $bEscape
316
             * @return string
317
             * @since  3.9.0
318
             */
319
            static private function ___getRowsOfKeyValuePair( array $aItem, array $aAllAttributes, $bEscape ) {
320
                $_aTRAttr                 = self::getElementAsArray( $aAllAttributes, 'tr' );
321
                $_aTRAttr[ 'class' ]      = self::getClassAttribute( 'key-value', self::getElement( $_aTRAttr, array( 'class' ), '' ) );
322
                $_aTDAttr                 = self::getElementAsArray( $aAllAttributes, 'td' );
323
                $_aTDAttr                 = array_filter( $_aTDAttr, 'is_scalar' );
324
                $_aPAttr                  = self::getElementAsArray( $aAllAttributes, array( 'p' ) );
325
                $_aTDAttrFirst            = self::getElementAsArray( $aAllAttributes, array( 'td', 0 ) ) + $_aTDAttr;
326
                $_aTDAttrFirst[ 'class' ] = self::getClassAttribute( 'column-key', self::getElement( $_aTDAttrFirst, array( 'class' ), '' ) );
327
                $_sOutput = '';
328
                foreach( $aItem as $_sColumnName => $_asValue ) {
329
                    $_sOutput .= "<tr " . self::getAttributes( $_aTRAttr ) . ">";
330
                    $_sOutput .= "<td " . self::getAttributes( $_aTDAttrFirst ) . ">"
331
                            . "<p " . self::getAttributes( $_aPAttr )  . ">" . self::___getHTMLEscaped( $_sColumnName, $bEscape ) . "</p>"
332
                         . "</td>";
333
                    $_sOutput .= self::___getColumnValue( $_asValue, $aAllAttributes, $bEscape, 1 );
334
                    $_sOutput .= "</tr>";
335
                }
336
                return $_sOutput;
337
            }
338
            /**
339
             * @return string
340
             * @since  3.9.0
341
             */
342
            static private function ___getRowsOfMultiColumns( array $aArray, array $aAllAttributes, $bEscape ) {
343
                $_aTRAttr = self::getElementAsArray( $aAllAttributes, 'tr' );
344
                $_sOutput = '';
345
                foreach( $aArray as $_iRowIndex => $_asValue ) {
346
                    if ( is_scalar( $_asValue ) ) {
347
                        $_sOutput .= "<tr " . self::getAttributes( $_aTRAttr ) . ">"
348
                                . self::___getColumnValue( $_asValue, $aAllAttributes, $bEscape, 0 )
349
                            . "</tr>";
350
                        continue;
351
                    }
352
                    $_aColumns = self::getAsArray( $_asValue );
353
                    $_sOutput .= "<tr " . self::getAttributes( $_aTRAttr ) . ">"
354
                            . self::___getColumns( $_aColumns, $aAllAttributes, $bEscape )
355
                        . "</tr>";
356
                }
357
                return $_sOutput;
358
            }
359
                static private function ___getColumns( array $aColumns, $aAllAttributes, $bEscape ) {
360
                    $_sOutput = '';
361
                    foreach( array_values( $aColumns ) as $_iIndex => $_asValue ) {
362
                        $_sOutput .= self::___getColumnValue( $_asValue, $aAllAttributes, $bEscape, $_iIndex );
363
                    }
364
                    return $_sOutput;
365
                }
366
367
            /**
368
             * @param  mixed   $mValue
369
             * @param  array   $aAllAttributes
370
             * @param  boolean $bEscape
371
             * @param  integer $iColumnIndex Zero-based column index
372
             * @return string
373
             * @since  3.9.0
374
             */
375
            static private function ___getColumnValue( $mValue, array $aAllAttributes, $bEscape, $iColumnIndex ) {
376
                $_aTDAttr    = self::getElementAsArray( $aAllAttributes, 'td' );
377
                $_aTDAttr    = array_filter( $_aTDAttr, 'is_scalar' );
378
                $_aTDAttrNth = self::getElementAsArray( $aAllAttributes, array( 'td', $iColumnIndex ) ) + $_aTDAttr;
379
                $_aTDAttrNth[ 'class' ] = self::getClassAttribute( 'column-value', self::getElement( $_aTDAttrNth, array( 'class' ), '' ) );
380
                if ( is_null( $mValue ) ) {
381
                    $mValue = '(null)';
382
                }
383
                $_aPAttr        = self::getElementAsArray( $aAllAttributes, 'p' );
384
                if ( is_scalar( $mValue ) ) {
385
                    return "<td " . self::getAttributes( $_aTDAttrNth ) . ">"
386
                        . "<p " . self::getAttributes( $_aPAttr )  . ">" . self::___getHTMLEscaped( $mValue, $bEscape ) . "</p>"
387
                       . "</td>";
388
                }
389
                if ( is_array( $mValue ) ) {
390
                    return self::isAssociativeArray( $mValue ) || self::isMultiDimensional( $mValue )
391
                        ? "<td " . self::getAttributes( $_aTDAttrNth ) . ">"
392
                            . self::getTableOfKeyValues( $mValue, $aAllAttributes )
393
                        . "</td>"
394
                        : "<td " . self::getAttributes( $_aTDAttrNth ) . ">"
395
                            // @todo may ought to be numeric-rows table
396
                            . self::___getList( $mValue, $aAllAttributes, $bEscape )
397
                        . "</td>";
398
                }
399
                return "<td " . self::getAttributes( $_aTDAttrNth ) . ">"
400
                        . '(' . gettype( $mValue ) . ')' . ( is_object( $mValue ) ? get_class( $mValue ) : '' )
401
                    . "</td>";
402
            }
403
                /**
404
                 * @param  array $aArray
405
                 * @param  array $aAllAttributes
406
                 * @param  boolean $bEscape
407
                 * @return string
408
                 * @since  3.9.0
409
                 */
410
                static private function ___getList( array $aArray, $aAllAttributes, $bEscape ) {
411
                    $_aULAttr = self::getElementAsArray( $aAllAttributes, 'ul' );
412
                    $_aLIAttr = self::getElementAsArray( $aAllAttributes, 'li' );
413
                    $_aULAttr[ 'class' ] = self::getClassAttribute( 'numeric', self::getElement( $_aULAttr, array( 'class' ), '' ) );
414
                    if ( empty( $aArray ) ) {
415
                        return '';
416
                    }
417
                    $_sList   = "<ul " . self::getAttributes( $_aULAttr ) . ">";
418
                    foreach( $aArray as $_asValue ) {
419
                        $_sItem  = is_array( $_asValue )
420
                            ? self::___getList( $_asValue, $aAllAttributes, $bEscape )
421
                            : self::___getHTMLEscaped( $_asValue, $bEscape );
422
                        $_sList .= "<li " . self::getAttributes( $_aLIAttr ) . ">"
423
                                . $_sItem
424
                            . "</li>";
425
                    }
426
                    $_sList  .= "</ul>";
427
                    return $_sList;
428
                }
429
430
}