source: trunk/lib/HTML.inc.php @ 534

Last change on this file since 534 was 534, checked in by anonymous, 9 years ago

Improved module maker validation output. Allow disabling cache at run time for ACL. Added ACL getList() method. Improved ACL CLI listing. Fixed app boomerang array initialization. Now retaining identical boomerang URLs if the key is different. Added a maximum boomerang time. Added a way to disable cache per request through a query string. Added validator isDecimal() method. Added disableSelectOptions() HTML method. Added getGravatarURL() method. Change how navigation page array is managed. Updated navigation currentPage() method to test an array of URLs.

File size: 15.0 KB
Line 
1<?php
2/*
3* The Strangecode Codebase - a general application development framework for PHP
4* For details visit the project site: <http://trac.strangecode.com/>
5* Copyright © 2014 Strangecode, LLC
6*
7* This program is free software: you can redistribute it and/or modify
8* it under the terms of the GNU General Public License as published by
9* the Free Software Foundation, either version 3 of the License, or
10* (at your option) any later version.
11*
12* This program is distributed in the hope that it will be useful,
13* but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15* GNU General Public License for more details.
16*
17* You should have received a copy of the GNU General Public License
18* along with this program.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21/*
22* HTML()
23*
24* Tools for building HTML from PHP data.
25*
26* @author   Quinn Comendant <quinn@strangecode.com>
27* @version  1.0
28* @since    11 Sep 2014 21:08:06
29*
30* Example of use:
31---------------------------------------------------------------------
32echo HTML::buttons(array(
33    array('name' => 'submit', 'value' => _("Save changes"), 'class' => 'small button', 'accesskey' => 's'),
34    array('name' => 'reset', 'value' => _("Reset"), 'class' => 'small button secondary', 'accesskey' => 'r'),
35    array('name' => 'cancel', 'value' => _("Cancel"), 'class' => 'small button secondary', 'accesskey' => 'c'),
36));
37---------------------------------------------------------------------
38*/
39
40class HTML
41{
42
43    // Browsers add names and ids of form controls as properties to the FORM. This results in the properties of the form being replaced.
44    // Use this list to warn the programmer if he uses an unsafe name.
45    // http://jibbering.com/faq/names/unsafe_names.html
46    static $unsafe_form_control_names = array('accept','acceptCharset','action','addBehavior','addEventListener','addEventSource','addRepetitionBlock','addRepetitionBlockByIndex','all','appendChild','applyElement','ariaBusy','ariaChecked','ariaControls','ariaDescribability','ariaDisabled','ariaExpanded','ariaFlowto','ariaHaspopup','ariaHidden','ariaInvalid','ariaLabelledby','ariaLevel','ariaMultiselect','ariaOwns','ariaPosinset','ariaPressed','ariaReadonly','ariaRequired','ariaSecret','ariaSelected','ariaSetsize','ariaValuemax','ariaValuemin','ariaValuenow','attachEvent','attributes','ATTRIBUTE_NODE','autocomplete','baseURI','behaviorUrns','blockDiraction','blur','canHaveChildren','canHaveHTML','CDATA_SECTION_NODE','checkValidity','childElementCount','childNodes','children','className','clearAttributes','click','clientHeight','clientLeft','clientTop','clientWidth','cloneNode','COMMENT_NODE','compareDocumentPosition','componentFromPoint','constructor','contains','contentEditable','currentStyle','data','detachEvent','dir','dispatchEvent','dispatchFormChange','dispatchFormInput','document','DOCUMENT_FRAGMENT_NODE','DOCUMENT_NODE','DOCUMENT_POSITION_CONTAINED_BY','DOCUMENT_POSITION_CONTAINS','DOCUMENT_POSITION_DISCONNECTED','DOCUMENT_POSITION_FOLLOWING','DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC','DOCUMENT_POSITION_PRECEDING','DOCUMENT_TYPE_NODE','dragDrop','elements','ELEMENT_NODE','encoding','enctype','ENTITY_NODE','ENTITY_REFERENCE_NODE','fireEvent','firstChild','firstElementChild','focus','getAdjacentText','getAttribute','getAttributeNode','getAttributeNodeNS','getAttributeNS','getBoundingClientRect','getClientRects','getElementsByClassName','getElementsByTagName','getElementsByTagNameNS','getExpression','getFeature','getUserData','hasAttribute','hasAttributeNS','hasAttributes','hasChildNodes','hasOwnProperty','hideFocus','id','innerHTML','innerText','insertAdjacentElement','insertAdjacentHTML','insertAdjacentText','insertBefore','isContentEditable','isDefaultNamespace','isDefaultNamespaceURI','isDisabled','isEqualNode','isMultiLine','isPrototypeOf','isSameNode','isSupported','isTextEdit','item','lang','language','lastChild','lastElementChild','length','localName','lookupPrefix','mergeAttributes','method','moveRepetitionBlock','msBlockProgression','msBoxSizing','name','namedItem','namespaceURI','nextSibling','nodeName','nodeType','nodeValue','normalize','NOTATION_NODE','offsetHeight','offsetWidth','onabort','onactivate','onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate','onbeforeeditfocus','onbeforepaste','onblur','onchage','onclick','onclosecapture','oncontextmenu','oncopy','oncut','ondblclick','ondeactivate','ondrag','ondragend','ondragenter','ondragleave','ondragover','onerror','onfocus','onfocusin','onfocusout','onhelp','oninput','onkeydown','onkeypress','onkeyup','onmousedown','onmouseenter','onmouseleave','onmousemove','onmousemultiwheel','onmouseout','onmouseover','onmouseup','onmousewheel','onmove','onmoveend','onmovestart','onOffBehavior','onpaste','onpropertychange','onreadystatechange','onresize','onresizeend','onresizestart','onscroll','onsearch','onselect','onselectstart','ontimeerror','onunload','outerHTML','outerText','ownerDocument','parentNode','parentTextEdit','prefix','previousElementSibling','previousSibling','PROCESSING_INSTRUCTION_NODE','propertyIsEnumerable','querySelector','querySelectorAll','quotes','releaseCapture','removeAttribute','removeAttributeNode','removeAttributeNS','removeBehavior','removeChild','removeEventListener','removeEventSource','removeExpression','removeNode','removeRepetitionBlock','repeatMax','repeatMin','repeatStart','repetitionBlocks','repetitionIndex','repetitionTemplate','repetitionType','replace','replaceAdjacentText','replaceChild','replaceNode','reset','resetFromData','role','runtimeStyle','schemaTypeInfo','scopeName','scrollByLines','scrollByPages','scrollHeight','scrollIntoView','scrollLeft','scrollTop','scrollWidth','selectNodes','selectSingleNode','setActive','setAttributeNode','setAttributeNodeNS','setAttributeNS','setCapture','setExpression','setIdAttribute','setIdAttributeNode','setIdAttributeNS','setUserData','sourceIndex','spellcheck','style','submit','swapNode','tabIndex','tagName','tagUrn','target','templateElements','text','textContent','TEXT_NODE','title','toLocaleString','toString','uniqueID','unselectable','unwatch','urns','valueOf','watch','window');
47
48    /**
49    * Prints submit buttons based on given array of submit button names and titles. If the array includes an 'href' key, the
50    * button is created using a <a> otherwise an <input type="
" /> is used.
51    *
52    * @access  public
53    * @param   array   $buttons     Array of buttons, the key being the button name, and value being the title of the button.
54    * @return  void
55    * @author   Quinn Comendant <quinn@strangecode.com>
56    * @version  1.0
57    * @since    12 Sep 2014 00:17:38
58    */
59    static public function printButtons($buttons=array(), $class='button-group')
60    {
61        $app =& App::getInstance();
62
63        if (!isset($buttons[0]) || !is_array($buttons[0])) {
64            $app =& App::getInstance();
65            $app->logMsg(sprintf('Incorrect parameters passed to HTML::buttons(): %s', getDump($buttons)), LOG_DEBUG, __FILE__, __LINE__);
66            return false;
67        }
68        if (empty($buttons)) {
69            return '';
70        }
71        ?><ul class="<?php echo oTxt($class) ?>"><?php
72        foreach ($buttons as $i => $b) {
73            $defaults = array();
74            $defaults['type'] = isset($b['type']) ? $b['type'] : 'submit';
75            $b = array_merge($defaults, $b);
76            if (isset($b['href'])) {
77                echo '<li><a';
78                foreach (array_diff_key($b, array('value' => null)) as $key => $value) {
79                    printf(' %s="%s"', $key, oTxt($value));
80                }
81                echo '>' . oTxt($b['value']) . '</a></li>';
82            } else if (isset($b['name'])) {
83                if (in_array($b['name'], self::$unsafe_form_control_names)) {
84                    $app->logMsg(sprintf('Unsafe form control name: %s', $b['name']), LOG_NOTICE, __FILE__, __LINE__);
85                }
86                $defaults['id'] = isset($b['id']) ? $b['id'] : sprintf('sc-%s-button', $b['name']);
87                echo '<li><input';
88                foreach ($b as $key => $value) {
89                    printf(' %s="%s"', $key, oTxt($value));
90                }
91                echo ' /></li>';
92            } else {
93                $app->logMsg(sprintf('Button missing name or href: %s', getDump($b)), LOG_ERR, __FILE__, __LINE__);
94                continue;
95            }
96        }
97        ?></ul><?php
98    }
99
100    /*
101    * Return an array of key-value pairs matching a database query for the given parameters. This is useful for
102    * injecting into HTML::printSelectOptions().
103    *
104    * @access   public
105    * @param  string $db_table         database table to lookup
106    * @param  string $key_column       column containing the human-readable titles for the select menu
107    * @param  string $val_column       column containing the computer values for the select menu
108    * @param  string $preselected      the currently selected value of the menu. compared to the $val_column
109    * @param  bool   $first            Optional first item; set true for a blank item, array for item with name and value.
110    * @param  string $extra_clause     SQL exclude clause. Something like "WHERE girls != 'buckteeth'"
111    * @return array                    Array of options suitable to pass into HTML::printSelectOptions().
112    * @author   Quinn Comendant <quinn@strangecode.com>
113    * @version  1.0
114    * @since    12 Sep 2014 11:43:23
115    */
116    static public function getSelectOptions($db_table, $key_column, $val_column, $preselected, $first=false, $extra_clause='', $sql_format='SELECT %1$s, %2$s FROM %3$s %4$s')
117    {
118        $db =& DB::getInstance();
119
120        // Sometimes preselected comes as a comma list.
121        if (!is_array($preselected)) {
122            $preselected = array($preselected);
123        }
124
125        $options = array();
126        if (true === $first) {
127            // Include a blank first option.
128            $options[] = array(
129                'value' => '',
130                'selected' => in_array('', $preselected),
131                'text' => '',
132            );
133        } else if (is_array($first)) {
134            // When the 'blank' first option needs a specific key->val pair.
135            foreach ($first as $key => $val) {
136                $options[] = array(
137                    'value' => $key,
138                    'selected' => in_array($key, $preselected),
139                    'text' => $val,
140                );
141            }
142        }
143
144        $db =& DB::getInstance();
145        $qid = $db->query(sprintf($sql_format, $key_column, $val_column, $db_table, $extra_clause), false);
146        while ($row = mysql_fetch_assoc($qid)) {
147            $options[] = array(
148                'value' => $row[$val_column],
149                'selected' => in_array($row[$val_column], $preselected),
150                'text' => $row[$key_column],
151            );
152        }
153        return $options;
154    }
155
156    /*
157    *
158    *
159    * @access   public
160    * @param    array   $options    Array of options, with keys: value, selected, text
161    * @param    array   $deselected Array of values to disable in options.
162    * @return   array               Same options, but those with a value matching an element in $deselected will have a 'disabled' element of true.
163    * @author   Quinn Comendant <quinn@strangecode.com>
164    * @version  1.0
165    * @since    24 Jul 2015 01:41:33
166    */
167    static public function disableSelectOptions($options, $deselected)
168    {
169        $app =& App::getInstance();
170        $n = sizeof($options);
171        for ($i=0; $i < $n; $i++) {
172            $app->logMsg(sprintf('Disable check: %s == %s', $options[$i]['value'], getDump($deselected)), LOG_DEBUG, __FILE__, __LINE__);
173            $options[$i]['disabled'] = in_array($options[$i]['value'], $deselected);
174        }
175        return $options;
176    }
177
178    /**
179     * Prints option fields for a select form. Works only with enum or set
180     * data types in table columns.
181     *
182     * @param  string $db_table     Database table to lookup
183     * @param  string $db_col       Database column to lookup
184     * @param  string $preselected  The currently selected value of the menu. compared to the $val_column
185     * @param  bool   $first        Optional first item; set true for a blank item, array for item with name and value.
186     * @param  bool   $sort         Sort the output.
187     */
188    static public function getSelectOptionsEnum($db_table, $db_col, $preselected, $first=false, $sort=false)
189    {
190        // Sometimes preselected comes as a comma list.
191        if (!is_array($preselected)) {
192            $preselected = array($preselected);
193        }
194
195        $options = array();
196        if (true === $first) {
197            // Include a blank first option.
198            $options[] = array(
199                'value' => '',
200                'selected' => in_array('', $preselected),
201                'text' => '',
202            );
203        } else if (is_array($first)) {
204            // When the 'blank' first option needs a specific key->val pair.
205            foreach ($first as $key => $val) {
206                $options[] = array(
207                    'value' => $key,
208                    'selected' => in_array($key, $preselected),
209                    'text' => $val,
210                );
211            }
212        }
213
214        $db =& DB::getInstance();
215        $values = $db->getEnumValues($db_table, $db_col, $sort);
216        foreach ($values as $v) {
217            $options[] = array(
218                'value' => $v,
219                'selected' => in_array($v, $preselected),
220                'text' => $v,
221            );
222        }
223
224        return $options;
225    }
226
227    /**
228     * Prints a select menu containing the specified values and keys of a table.
229     *
230     */
231    static public function printSelectOptions($options)
232    {
233        if (!isset($options) || !is_array($options)) {
234            $app =& App::getInstance();
235            $app->logMsg(sprintf('Incorrect parameters passed to HTML::printSelectOptions(): %s', getDump($options)), LOG_DEBUG, __FILE__, __LINE__);
236            return false;
237        }
238        if (empty($options)) {
239            return '';
240        }
241
242        foreach ($options as $o) {
243            printf('<option value="%s"%s%s>%s</option>',
244                oTxt($o['value']),
245                (isset($o['selected']) && $o['selected'] ? ' selected' : ''),
246                (isset($o['disabled']) && $o['disabled'] ? ' disabled' : ''),
247                oTxt($o['text'])
248            );
249        }
250    }
251
252    /**
253     * Get a Gravatar URL for a specified email address.
254     *
255     * @param string $email The email address
256     * @param string $size Size in pixels, defaults to 80px [ 1 - 2048 ]
257     * @param string $d Default imageset to use [ 404 | mm | identicon | monsterid | wavatar ]
258     * @param string $r Maximum rating (inclusive) [ g | pg | r | x ]
259     * @return String containing a URL to a gravatar image.
260     * @source http://gravatar.com/site/implement/images/php/
261     */
262    static public function getGravatarURL($email, $size=80, $defset='mm', $rating='g') {
263        return sprintf('https://www.gravatar.com/avatar/%s?s=%s&d=%s&r=%s',
264            md5(strtolower(trim($email))),
265            $size,
266            $defset,
267            $rating
268        );
269    }
270}
Note: See TracBrowser for help on using the repository browser.