/** * Detect format * * Detect which format should be used to output the data * * @return string */ protected function _detect_format() { // A format has been passed as an argument in the URL and it is supported if (\Input::param('format') and $this->_supported_formats[\Input::param('format')]) { return \Input::param('format'); } // Otherwise, check the HTTP_ACCEPT (if it exists and we are allowed) if ($acceptable = \Input::server('HTTP_ACCEPT') and \Config::get('rest.ignore_http_accept') !== true) { // If anything is accepted, and we have a default, return that if ($acceptable == '*/*' and !empty($this->rest_format)) { return $this->rest_format; } // Split the Accept header and build an array of quality scores for each format $fragments = new \CachingIterator(new \ArrayIterator(preg_split('/[,;]/', \Input::server('HTTP_ACCEPT')))); $acceptable = array(); $next_is_quality = false; foreach ($fragments as $fragment) { $quality = 1; // Skip the fragment if it is a quality score if ($next_is_quality) { $next_is_quality = false; continue; } elseif ($fragments->hasNext()) { $next = $fragments->getInnerIterator()->current(); if (strpos($next, 'q=') === 0) { list($key, $quality) = explode('=', $next); $next_is_quality = true; } } $acceptable[$fragment] = $quality; } // Sort the formats by score in descending order uasort($acceptable, function ($a, $b) { $a = (double) $a; $b = (double) $b; return $a > $b ? -1 : 1; }); // Check each of the acceptable formats against the supported formats foreach ($acceptable as $pattern => $quality) { // The Accept header can contain wildcards in the format $find = array('*', '/'); $replace = array('.*', '\\/'); $pattern = '/^' . str_replace($find, $replace, $pattern) . '$/'; foreach ($this->_supported_formats as $format => $mime) { if (preg_match($pattern, $mime)) { return $format; } } } } // End HTTP_ACCEPT checking // Well, none of that has worked! Let's see if the controller has a default if (!empty($this->rest_format)) { return $this->rest_format; } // Just use the default format return \Config::get('rest.default_format'); }
<?php /** * CachingIterator - "Um olho no peixe e outro no gato", está sempre uma posição a frente em relação ao iterator. */ $arr = ['eu' => 'tenho', 'sou' => 'keys', 'um' => 'para', 'array' => 'comparar', 'assoc' => 'galera']; $iterator = new CachingIterator(new ArrayIterator($arr)); var_dump($iterator->current()); // null var_dump($iterator->getInnerIterator()->current()); // string(5) "tenho" foreach ($iterator as $key => $value) { echo "Atual: {$value} - "; $proximoValue = $iterator->getInnerIterator()->current(); echo "Proximo: {$proximoValue} \n"; }
<?php /** * Előre tekintés */ $data = new ArrayObject(range(0, 9)); $iterator = new CachingIterator($data->getIterator(), CachingIterator::FULL_CACHE); foreach ($iterator as $key => $value) { printf("Key %s => Value %s, Current %s, HasNext %b, Next %s\n", $key, $value, $iterator->current(), $iterator->hasNext(), $iterator->getInnerIterator()->current()); var_dump($iterator->getCache()); }
/** * Finds the line where the requested PHP Token appears * * @param string $type PHP Token constant or a custom one (@see tokenChar()) * @param string $name Name of the token (ie variable name) * @param int $skip How many line should I skip from the beginning? * * @return int|null Returns the corrispongin line or null if not found */ protected function findToken($type, $name, $skip = 0) { $tokens = token_get_all($this->code); $iterator = new ArrayIterator($tokens); $collection = new CachingIterator($iterator, CachingIterator::TOSTRING_USE_CURRENT); $ignoreSkip = false; // Ok let's start looking for the requested token foreach ($collection as $token) { $line = 0; if (is_string($token)) { $info['token'] = $this->tokenChar($token); $info['value'] = $token; } else { $info['token'] = token_name($token[0]); $info['value'] = $token[1]; $line = $token[2]; } // If I have the skip argument I have to skip the first lines (literal chars are always skipped since they // don't report the line they're in) if ($skip && $line < $skip && !$ignoreSkip) { continue; } // Ok, now I can stop checking for the skip (again, literal chars have no line info, otherwise I'll // keep skipping them all the time $ignoreSkip = true; // Ok token found, let's get the line if ($info['token'] == $type && $info['value'] == $name) { // If it's an array, that's easy if (is_array($token)) { return $token[2]; } else { // It's a string, I have to fetch the next token so I'll have the proper line number // To be sure, I have to iterate until I finally get an array for the token $next = null; while (!is_array($next)) { $next = $collection->getInnerIterator()->current(); // The next token is not an array (ie it's a char like ;.=?)? Move the iterator forward and fetch // the next token if (!is_array($next)) { $collection->getInnerIterator()->next(); continue; } return $next[2]; } } } } return null; }
public function pages($config = array()) { $config = new Library\ObjectConfig($config); $config->append(array('pages' => array(), 'active' => null, 'attribs' => array('class' => array('nav')))); $result = ''; $first = true; $last_level = 0; $pages = clone $config->pages; // We use a CachingIterator to peek ahead to the next item so that we can properly close elements $collection = new \CachingIterator($pages->getIterator(), \CachingIterator::TOSTRING_USE_KEY); foreach ($collection as $page) { $next_page = null; if ($collection->hasNext()) { $next_page = $collection->getInnerIterator()->current(); } $next_level = is_object($next_page) ? count(explode('/', $next_page->path)) : false; $level = count(explode('/', $page->path)); // Start a new level if ($level > $last_level) { $attributes = $first ? ' ' . $this->buildAttributes($config->attribs) : ''; $result .= "<ul{$attributes}>"; // Used to put the title in the menu if ($first && $config->title) { $result .= '<li class="nav-header">' . $config->title . "</li>"; } $first = false; } $classes = array(); if ($config->active) { if (in_array($page->id, array_merge($config->active->getParentIds(), (array) $config->active->id))) { $classes[] = 'active'; } if ($page->id == $config->active->id) { $classes[] = 'current'; } foreach ($config->pages as $value) { if (strpos($value->path, $page->path . '/') === 0) { $classes[] = 'parent'; break; } } } if ($page->type == 'separator') { $classes[] = 'nav-header'; } $result .= '<li' . ($classes ? ' class="' . implode(' ', $classes) . '"' : '') . ">"; switch ($page->type) { case 'component': $link = $this->getTemplate()->getView()->getRoute($page->getLink()->getQuery()); $result .= '<a href="' . (string) $link . '">'; $result .= $page->title; $result .= '</a>'; break; case 'menulink': $page_linked = $this->getObject('application.pages')->getPage($page->getLink()->query['Itemid']); $result .= '<a href="' . $page_linked->getLink() . '">'; $result .= $page->title; $result .= '</a>'; break; case 'separator': $result .= '<span class="separator ' . ($config->disabled ? 'nolink' : '') . '">' . $page->title . '</span>'; break; case 'url': $result .= '<a href="' . $page->getLink() . '">'; $result .= $page->title; $result .= '</a>'; break; case 'redirect': $result .= '<a href="' . $page->route . '">'; $result .= $page->title; $result .= '</a>'; } //$result .= $level; if ($level < $next_level) { // don't close <li> } elseif ($level === $next_level) { $result .= "</li>"; } elseif ($next_level === false || $level > $next_level) { // Last one of the level $result .= "</li>"; for ($i = 0; $i < $level - $next_level; ++$i) { if ($next_level === false) { $result .= "</ul>"; } else { $result .= "</ul></li>"; } } } $last_level = $level; } return $result; }
} } } ?> # Change Log All notable changes to this project will be documented in this file. This projects adheres to [Semantic Versioning](http://semver.org/) and [Keep a CHANGELOG](http://keepachangelog.com/). <?php foreach ($changelog as $log) { if ('Unreleased' === $log->version) { echo '## [', $log->version, '][unreleased]', "\r\n"; } else { echo '## [', $log->version, '] - ', $log->date, "\r\n"; } render_changes($log->changes); echo "\r\n"; } $collection = new CachingIterator(new ArrayIterator($changelog), CachingIterator::TOSTRING_USE_CURRENT); foreach ($collection as $log) { if ($collection->hasNext()) { $prev = $collection->getInnerIterator()->current(); if ('Unreleased' === $log->version) { echo '[unreleased]: https://github.com/pronamic/wp-pronamic-ideal/compare/', $prev->version, '...', 'HEAD', "\r\n"; } else { echo '[', $log->version, ']: https://github.com/pronamic/wp-pronamic-ideal/compare/', $prev->version, '...', $log->version, "\r\n"; } } }