/** * Autoload a class by name. <b>This function should not be called directly.</b> * * @internal * * @param string $name The name of the class to load * * @return bool */ public static function autoload($name) { $names = array($name); if (self::$autoload_harder) { if (!class_exists(__NAMESPACE__ . '\\Util\\String')) { require_once __DIR__ . '/Util/String.php'; } // Break the class name up, so IterableRenderable will search for // Iterable and Renderable and MyFooClass will search for My, MyFoo, // FooClass and Class. // Additional complexity: 2 * (nComponents - 1) $parts = \Jerity\Util\String::splitCamelCase($name); $the_parts = $parts; array_pop($the_parts); $accumulator = ''; foreach ($the_parts as $part) { $accumulator .= $part; $names[] = $accumulator; } $the_parts = array_reverse($parts); array_pop($the_parts); $accumulator = ''; $new_names = array(); foreach ($the_parts as $part) { $accumulator = $part . $accumulator; $new_names[] = $accumulator; } $names = array_merge($names, array_reverse($new_names)); } foreach ($names as $name) { $path = preg_replace('/^\\\\?' . __NAMESPACE__ . '\\\\/', '', $name); $path = str_replace('\\', '/', $path); foreach (array_keys(self::$autoload_dirs) as $dir) { $target_file = $dir . '/' . $path . '.php'; if (file_exists($target_file)) { include_once $target_file; if (class_exists($name)) { return true; } } } } return false; }
/** * @dataProvider formatBytesProvider() * @depends NumberTest::parseBytes() * @group inflector */ public function testFormatBytes($n, $si, $dp, $prefix, $symbol, $expected) { $this->assertSame($expected, String::formatBytes($n, $si, $dp, $prefix, $symbol)); }
/** * Performs a simple redirection to the specified URL (see below for details * on shorthand URLs). * * Shorthand URLs work as follows: * - <kbd>/^#/</kbd> -- Appends a URL hash to the current URL. * - <kbd>/^?/</kbd> -- Sets the query string for the current page. * - <kbd>/^&/</kbd> -- Appends all specified queries to the URL (Overwrite). * - <kbd>/^&&/</kbd> -- Appends all specified queries to the URL (No overwrite). * - <kbd>/^\//</kbd> -- Redirects to URL relative to root of site (prepends domain). * - <kbd>/^[a-z]*:\/\//</kbd> -- Redirects to absolute URL. * * There is also support for pausing redirects for debugging purposes. * * @see Debug::pauseOnRedirect() * * @param string $url Where to redirect to. * @param bool $permanent Whether to redirect permanently (default: false) * * @throws RedirectorException */ public static function redirect($url = null, $permanent = false) { $url = URL::ize($url); # Get the current render context $ctx = RenderContext::get(); # Check whether we should suspend redirects if (Debug::isEnabled() && (Debug::pauseOnRedirect() || Error::hasErred())) { echo '<div>'; printf('<p><strong>Paused Redirect:</strong> <a href="%s">%s</a></p>', $url, String::escapeHTML($url)); if (Error::hasErred()) { echo '<p><strong>Last Error:</strong></p>'; Debug::out(Error::getLast()); } echo '</div>'; exit; } # Write and close session to avoid losing changes: session_write_close(); # Perform redirect if (headers_sent()) { switch ($ctx->getLanguage()) { case RenderContext::LANG_HTML: case RenderContext::LANG_XHTML: $url = String::escapeJS($url, false); echo '<script type="text/javascript">window.location = \'' . $url . '\';</script>"'; break; default: throw new RedirectorException('Cannot redirect - headers sent and invalid render context.'); } } else { if ($permanent) { header('HTTP/1.1 301 Moved Permanently'); } header('Location: ' . $url); } # Output message just in case we have a silly browser [RFC2616] if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] != 'HEAD') { switch ($ctx->getLanguage()) { case RenderContext::LANG_HTML: case RenderContext::LANG_XHTML: printf('Redirecting to: <a href="%s">%s</a>.', $url, String::escapeHTML($url)); break; default: # Ignore } } # We've redirected, so stop executing now exit; }
/** * Outputs the information in the correct format. * * @param bool $verbose Whether to output full information. * * @return string The benchmark data up to the current point. */ protected static function output($verbose = false) { # Choose comment string based on render context. $ctx = RenderContext::get(); switch ($ctx->getLanguage()) { case RenderContext::LANG_HTML: case RenderContext::LANG_XHTML: $prefix = '<!-- Benchmark:'; $postfix = '-->'; break; case RenderContext::LANG_JS: case RenderContext::LANG_CSS: $prefix = '/*** Benchmark:'; $postfix = '***/'; break; default: throw new BenchmarkException('Unsupported render context.'); } # Retrieve required data. $a =& self::$data[0]; $b =& self::$data[count(self::$data) - 1]; # Calculate time differences. $real = $b['time']['real'] - $a['time']['real']; $user = $b['time']['user'] - $a['time']['user']; $system = $b['time']['system'] - $a['time']['system']; # Generate output. $output = $prefix; if ($verbose) { $output .= PHP_EOL . ' '; $output .= sprintf('Time: %.5fs real, %.5fs user, %.5fs system', $real, $user, $system); if (isset($b['memory'])) { $output .= PHP_EOL . ' '; $output .= sprintf('Memory: %s current, %s peak', String::formatBytes($b['memory']['current'], false, null, 2), String::formatBytes($b['memory']['peak'], false, null, 2)); } $output .= PHP_EOL . ' '; $output .= sprintf('Queries: %d', $b['query']['count']); if (isset($b['cache'])) { $output .= PHP_EOL . ' '; $output .= sprintf('Cache: %d hits, %d misses, %s used, %s available', $b['cache']['hits'], $b['cache']['misses'], String::formatBytes($b['cache']['memory_used'], false, null, 2), String::formatBytes($b['cache']['memory_limit'], false, null, 2)); } $output .= ' '; } else { $output .= ' '; $output .= sprintf('Time: %.5fs', $real); $output .= '; '; $output .= sprintf('Memory: %s', String::formatBytes($b['memory']['peak'], false, null, 2)); $output .= '; '; $output .= sprintf('Queries: %d', $b['query']['count']); $output .= ' '; } $output .= $postfix . PHP_EOL; if (self::$print) { echo $output; } return $output; }
/** * Adds a footnote to the page and returns a link to the footnote item. * * @param string $footnote The footnote text * @param boolean $escape Whether to escape the footnote content. * * @return string The rendered footnote link. */ public function add($footnote, $escape = false) { $this->footnotes[] = $escape ? String::escape($footnote) : $footnote; $index = count($this->footnotes); $attrs = array('class' => $this->class_link, 'href' => '#' . $this->fragment . $index, 'id' => $this->fragment . '-' . $index); return Tag::renderTag('a', $attrs, $index); }
/** * Generate a list of records in the given table. * * If the given table is null, then all tables defined in the schema will be * listed. * * @param string $table The table from which records should be listed. * * @return string */ public function generateListPage($table) { ob_start(); if (is_null($table)) { // list all tables $this->outputPageHeader('All tables'); # $_GET[self::FORM_PREFIX.'_table'] echo "<ul>\n"; foreach (array_keys($this->schema) as $table) { echo '<li><a href="' . $this->generateActionUrl('list') . '&' . self::FORM_PREFIX . '_table=' . rawurlencode($table) . '">' . String::escape($table) . "</a></li>\n"; } echo "</ul>\n"; } else { // specific table $this->outputPageHeader('Table ' . $table); $db = $this->db; $primary_field = $this->schema[$table]['_primary']; // join with belongsTo tables (and hasMany?) if (count($this->schema[$table]['_belongsTo'])) { $sql = 'SELECT * FROM `' . $table . '` ORDER BY `' . $primary_field . '`'; $select = array(); $from = array(''); # critical hack to include one LEFT JOIN foreach (array_keys($this->schema[$table]['fields']) as $field) { if (isset($this->schema[$table]['_belongsTo'][$field])) { $linked_table = $this->schema[$table]['_belongsTo'][$field]; if (isset($this->schema[$linked_table]['_primary'])) { $linked_field = $this->schema[$linked_table]['_primary']; $linked_display_field = $this->schema[$linked_table]['_primary']; if (isset($this->schema[$linked_table]['_display'])) { $linked_display_field = $this->schema[$linked_table]['_display']; } $select[] = 'CONCAT(`' . $linked_table . '`.`' . $linked_display_field . '`, \' [\', `' . $table . '`.`' . $field . '`, \']\') AS `' . $field . '`'; $from[] = '`' . $linked_table . '` ON `' . $linked_table . '`.`' . $linked_field . '` = `' . $table . '`.`' . $field . '`'; } else { $select[] = '`' . $table . '`.`' . $field . '`'; } } else { $select[] = '`' . $table . '`.`' . $field . '`'; } } $sql = 'SELECT ' . implode(', ', $select) . ' FROM `' . $table . '`' . implode(' LEFT JOIN ', $from) . ' ORDER BY `' . $table . '`.`' . $primary_field . '`'; } else { $sql = 'SELECT * FROM `' . $table . '` ORDER BY `' . $primary_field . '`'; } $stmt = $db->prepare($sql); $stmt->execute(); if ($stmt->rowCount()) { $header = false; echo "<table class=\"scaffold\">\n<thead>\n<tr>"; $row = $stmt->fetch(\PDO::FETCH_ASSOC); foreach (array_keys($row) as $col) { echo '<th>' . String::escapeHTML($col) . '</th>'; } echo '<th class="actions">Actions</th>'; echo "</tr>\n</thead>\n<tfoot></tfoot>\n<tbody>\n"; $i = 0; do { echo '<tr class="zebra' . $i++ % 2 . '">'; foreach ($row as $k => $v) { if ($k === $primary_field) { echo '<td class="primary">' . String::escapeHTML($v) . '</td>'; } else { echo '<td>' . String::escapeHTML($v) . '</td>'; } } echo '<td class="actions"><a href="' . $this->generateActionUrl('update', $row[$primary_field]) . '">Edit</a> <a href="' . $this->generateActionUrl('delete', $row[$primary_field]) . '">Delete</a></th>'; echo "</tr>\n"; } while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)); echo "</tbody>\n</table>\n"; } else { echo '<p>No rows to display.</p>', "\n"; } echo '<p><a href="' . $this->generateActionUrl('create') . '">New item</a></p>', "\n"; } $this->outputPageFooter(); return ob_get_clean(); }
/** * Render a custom block of HTML. * * @param string $error An error message to show, if applicable. * * @return string */ public function render($error = null) { $out = ''; if (isset($this['label'])) { $labelcontent = String::escape($this['label']) . ':'; if (isset($this['required']) && $this['required']) { $labelcontent .= ' <em>Required</em>'; } $out .= Tag::renderTag('label', array('for' => $this['id']), $labelcontent) . "\n"; } if (isset($this['content'])) { $content = $this['content']; } else { $content = ''; } if ($error) { $out .= self::renderError($this->props, $error); if (!isset($this->props['class'])) { $this->props['class'] = 'haserror'; } elseif (!preg_match('/(?:^| )haserror(?:$| )/', $this->props['class'])) { $this->props['class'] .= ' haserror'; } } $attrs = array_diff_key($this->props, array_flip(array('content', 'escape', 'name', 'type'))); $out .= Tag::renderTag('div', $attrs, $content) . "\n"; return $out; }
/** * Renders a tag according the the current render context. * * Note that content is <b>never</b> escaped. Specifying <tt>false</tt> for the content will force * an object tag in XML-based languages. An object tag will also always be generated for XHTML tags * which cannot contain content. * * @param string $tag The tag to render. * @param array $attrs An associative array of additional attributes. * @param string $content The inline content. * * @return string */ public static function renderTag($tag, array $attrs = array(), $content = null) { $tag = strtolower($tag); # Check for and warn about deprecated elements and attributes. if (Debug::isEnabled()) { self::checkDeprecatedElements($tag); self::checkDeprecatedAttributes($tag, array_keys($attrs)); } # Check whether we need to account for XML. $ctx = RenderContext::get(); $is_xml = $ctx->isXMLSyntax(); $r = '<' . $tag; foreach ($attrs as $k => $v) { if ($v === false || $k[0] === '_') { // attributes which should never be output continue; } if ($v === true) { // handle checked="checked", etc $v = $k; } $r .= ' ' . strtolower($k) . '="' . String::escape($v) . '"'; } if ($is_xml && ($content === false || self::isAlwaysEmpty($tag))) { $r .= ' />'; } else { $r .= '>'; } if (!is_null($content) && $content !== false) { if ($content !== '') { if (self::shouldMaskContent($tag)) { $r .= PHP_EOL . self::getContentMask($tag, true) . PHP_EOL; } $r .= $content; if (self::shouldMaskContent($tag)) { $r .= PHP_EOL . self::getContentMask($tag, false) . PHP_EOL; } } $r .= '</' . $tag . '>'; } return $r; }