"],_default:[0,"",""]};$.optgroup=$.option,$.tbody=$.tfoot=$.colgroup=$.caption=$.thead,$.th=$.td;function _(a,b){var c="undefined"!=typeof a.getElementsByTagName?a.getElementsByTagName(b||"*"):"undefined"!=typeof a.querySelectorAll?a.querySelectorAll(b||"*"):[];return void 0===b||b&&n.nodeName(a,b)?n.merge([a],c):c}function aa(a,b){for(var c=0,d=a.length;d>c;c++)N.set(a[c],"globalEval",!b||N.get(b[c],"globalEval"))}var ba=/<|?\w+;/;function ca(a,b,c,d,e){for(var f,g,h,i,j,k,l=b.createDocumentFragment(),m=[],o=0,p=a.length;p>o;o++)if(f=a[o],f||0===f)if("object"===n.type(f))n.merge(m,f.nodeType?[f]:f);else if(ba.test(f)){g=g||l.appendChild(b.createElement("div")),h=(Y.exec(f)||["",""])[1].toLowerCase(),i=$[h]||$._default,g.innerHTML=i[1]+n.htmlPrefilter(f)+i[2],k=i[0];while(k--)g=g.lastChild;n.merge(m,g.childNodes),g=l.firstChild,g.textContent=""}else m.push(b.createTextNode(f));l.textContent="",o=0;while(f=m[o++])if(d&&n.inArray(f,d)>-1)e&&e.push(f);else if(j=n.contains(f.ownerDocument,f),g=_(l.appendChild(f),"script"),j&&aa(g),c){k=0;while(f=g[k++])Z.test(f.type||"")&&c.push(f)}return l}!function(){var a=d.createDocumentFragment(),b=a.appendChild(d.createElement("div")),c=d.createElement("input");c.setAttribute("type","radio"),c.setAttribute("checked","checked"),c.setAttribute("name","t"),b.appendChild(c),l.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,b.innerHTML="",l.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue}();var da=/^key/,ea=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,fa=/^([^.]*)(?:\.(.+)|)/;function ga(){return!0}function ha(){return!1}function ia(){try{return d.activeElement}catch(a){}}function ja(a,b,c,d,e,f){var g,h;if("object"==typeof b){"string"!=typeof c&&(d=d||c,c=void 0);for(h in b)ja(a,h,c,d,b[h],f);return a}if(null==d&&null==e?(e=c,d=c=void 0):null==e&&("string"==typeof c?(e=d,d=void 0):(e=d,d=c,c=void 0)),e===!1)e=ha;else if(!e)return this;return 1===f&&(g=e,e=function(a){return n().off(a),g.apply(this,arguments)},e.guid=g.guid||(g.guid=n.guid++)),a.each(function(){n.event.add(this,b,e,d,c)})}n.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.get(a);if(r){c.handler&&(f=c,c=f.handler,e=f.selector),c.guid||(c.guid=n.guid++),(i=r.events)||(i=r.events={}),(g=r.handle)||(g=r.handle=function(b){return"undefined"!=typeof n&&n.event.triggered!==b.type?n.event.dispatch.apply(a,arguments):void 0}),b=(b||"").match(G)||[""],j=b.length;while(j--)h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o&&(l=n.event.special[o]||{},o=(e?l.delegateType:l.bindType)||o,l=n.event.special[o]||{},k=n.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&n.expr.match.needsContext.test(e),namespace:p.join(".")},f),(m=i[o])||(m=i[o]=[],m.delegateCount=0,l.setup&&l.setup.call(a,d,p,g)!==!1||a.addEventListener&&a.addEventListener(o,g)),l.add&&(l.add.call(a,k),k.handler.guid||(k.handler.guid=c.guid)),e?m.splice(m.delegateCount++,0,k):m.push(k),n.event.global[o]=!0)}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,m,o,p,q,r=N.hasData(a)&&N.get(a);if(r&&(i=r.events)){b=(b||"").match(G)||[""],j=b.length;while(j--)if(h=fa.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=n.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,m=i[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),g=f=m.length;while(f--)k=m[f],!e&&q!==k.origType||c&&c.guid!==k.guid||h&&!h.test(k.namespace)||d&&d!==k.selector&&("**"!==d||!k.selector)||(m.splice(f,1),k.selector&&m.delegateCount--,l.remove&&l.remove.call(a,k));g&&!m.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||n.removeEvent(a,o,r.handle),delete i[o])}else for(o in i)n.event.remove(a,o+b[j],c,d,!0);n.isEmptyObject(i)&&N.remove(a,"handle events")}},dispatch:function(a){a=n.event.fix(a);var b,c,d,f,g,h=[],i=e.call(arguments),j=(N.get(this,"events")||{})[a.type]||[],k=n.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=n.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,c=0;while((g=f.handlers[c++])&&!a.isImmediatePropagationStopped())(!a.rnamespace||a.rnamespace.test(g.namespace))&&(a.handleObj=g,a.data=g.data,d=((n.event.special[g.origType]||{}).handle||g.handler).apply(f.elem,i),void 0!==d&&(a.result=d)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&("click"!==a.type||isNaN(a.button)||a.button<1))for(;i!==this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(d=[],c=0;h>c;c++)f=b[c],e=f.selector+" ",void 0===d[e]&&(d[e]=f.needsContext?n(e,this).index(i)>-1:n.find(e,this,null,[i]).length),d[e]&&d.push(f);d.length&&g.push({elem:i,handlers:d})}return h]*)\/>/gi,la=/' . "\n";
+ $output .= '' . "\n";
}
}
} else {
@@ -618,9 +631,11 @@ class Assets
}
/**
- * Minify and concatenate CSS.
+ * Minify and concatenate CSS
*
- * @return string
+ * @param string $group
+ *
+ * @return bool|string
*/
protected function pipelineCss($group = 'head')
{
@@ -679,6 +694,7 @@ class Assets
// Write file
if (strlen(trim($buffer)) > 0) {
file_put_contents($absolute_path, $buffer);
+
return $relative_path . $key;
} else {
return false;
@@ -688,6 +704,8 @@ class Assets
/**
* Minify and concatenate JS files.
*
+ * @param string $group
+ *
* @return string
*/
protected function pipelineJs($group = 'head')
@@ -737,6 +755,7 @@ class Assets
// Write file
if (strlen(trim($buffer)) > 0) {
file_put_contents($absolute_path, $buffer);
+
return $relative_path . $key;
} else {
return false;
@@ -782,9 +801,7 @@ class Assets
*/
public function exists($asset)
{
- if (isset($this->collections[$asset]) ||
- isset($this->css[$asset]) ||
- isset($this->js[$asset])) {
+ if (isset($this->collections[$asset]) || isset($this->css[$asset]) || isset($this->js[$asset])) {
return true;
} else {
return false;
@@ -826,7 +843,8 @@ class Assets
*/
public function resetJs()
{
- $this->js = array();
+ $this->js = [];
+ $this->inline_js = [];
return $this;
}
@@ -838,15 +856,28 @@ class Assets
*/
public function resetCss()
{
- $this->css = array();
+ $this->css = [];
+ $this->inline_css = [];
return $this;
}
/**
- * Add all CSS assets within $directory (relative to public dir).
+ * Add all JavaScript assets within $directory
*
- * @param string $directory Relative to $this->public_dir
+ * @param string $directory Relative to the Grav root path, or a stream identifier
+ *
+ * @return $this
+ */
+ public function addDirJs($directory)
+ {
+ return $this->addDir($directory, self::JS_REGEX);
+ }
+
+ /**
+ * Add all CSS assets within $directory
+ *
+ * @param string $directory Relative to the Grav root path, or a stream identifier
*
* @return $this
*/
@@ -858,7 +889,7 @@ class Assets
/**
* Add all assets matching $pattern within $directory.
*
- * @param string $directory Relative to $this->public_dir
+ * @param string $directory Relative to the Grav root path, or a stream identifier
* @param string $pattern (regex)
*
* @return $this
@@ -866,13 +897,15 @@ class Assets
*/
public function addDir($directory, $pattern = self::DEFAULT_REGEX)
{
- // Check if public_dir exists
- if (!is_dir($this->assets_dir)) {
- throw new Exception('Assets: Public dir not found');
+ $root_dir = rtrim(ROOT_DIR, '/');
+
+ // Check if $directory is a stream.
+ if (strpos($directory, '://')) {
+ $directory = self::$grav['locator']->findResource($directory, null);
}
// Get files
- $files = $this->rglob($this->assets_dir . DIRECTORY_SEPARATOR . $directory, $pattern, $this->assets_dir);
+ $files = $this->rglob($root_dir . DIRECTORY_SEPARATOR . $directory, $pattern, $root_dir . '/');
// No luck? Nothing to do
if (!$files) {
@@ -881,27 +914,25 @@ class Assets
// Add CSS files
if ($pattern === self::CSS_REGEX) {
- $this->css = array_unique(array_merge($this->css, $files));
+ foreach ($files as $file) {
+ $this->addCss($file);
+ }
+
return $this;
}
// Add JavaScript files
if ($pattern === self::JS_REGEX) {
- $this->js = array_unique(array_merge($this->js, $files));
+ foreach ($files as $file) {
+ $this->addJs($file);
+ }
+
return $this;
}
- // Unknown pattern. We must poll to know the extension :(
+ // Unknown pattern.
foreach ($files as $asset) {
- $info = pathinfo($asset);
- if (isset($info['extension'])) {
- $ext = strtolower($info['extension']);
- if ($ext === 'css' && !in_array($asset, $this->css)) {
- $this->css[] = $asset;
- } elseif ($ext === 'js' && !in_array($asset, $this->js)) {
- $this->js[] = $asset;
- }
- }
+ $this->add($asset);
}
return $this;
@@ -918,8 +949,8 @@ class Assets
*/
protected function isRemoteLink($link)
{
- return ('http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8)
- || '//' === substr($link, 0, 2));
+ return ('http://' === substr($link, 0, 7) || 'https://' === substr($link, 0, 8) || '//' === substr($link, 0,
+ 2));
}
/**
@@ -972,18 +1003,18 @@ class Assets
* Download and concatenate the content of several links.
*
* @param array $links
- * @param bool $css
+ * @param bool $css
*
* @return string
*/
protected function gatherLinks(array $links, $css = true)
{
-
-
$buffer = '';
$local = true;
foreach ($links as $asset) {
+ $relative_dir = '';
+
$link = $asset['asset'];
$relative_path = $link;
@@ -1034,8 +1065,8 @@ class Assets
/**
* Finds relative CSS urls() and rewrites the URL with an absolute one
*
- * @param $file the css source file
- * @param $relative_path relative path to the css file
+ * @param string $file the css source file
+ * @param string $relative_path relative path to the css file
*
* @return mixed
*/
@@ -1046,23 +1077,19 @@ class Assets
// Find any css url() elements, grab the URLs and calculate an absolute path
// Then replace the old url with the new one
- $file = preg_replace_callback(
- self::CSS_URL_REGEX,
- function ($matches) use ($relative_path) {
+ $file = preg_replace_callback(self::CSS_URL_REGEX, function ($matches) use ($relative_path) {
- $old_url = $matches[1];
+ $old_url = $matches[1];
- // ensure this is not a data url
- if (strpos($old_url, 'data:') === 0) {
- return $matches[0];
- }
+ // ensure this is not a data url
+ if (strpos($old_url, 'data:') === 0) {
+ return $matches[0];
+ }
- $new_url = $this->base_url . ltrim(Utils::normalizePath($relative_path . '/' . $old_url), '/');
+ $new_url = $this->base_url . ltrim(Utils::normalizePath($relative_path . '/' . $old_url), '/');
- return str_replace($old_url, $new_url, $matches[0]);
- },
- $file
- );
+ return str_replace($old_url, $new_url, $matches[0]);
+ }, $file);
return $file;
}
@@ -1076,16 +1103,13 @@ class Assets
*/
protected function moveImports($file)
{
- $this->imports = array();
+ $this->imports = [];
- $file = preg_replace_callback(
- self::CSS_IMPORT_REGEX,
- function ($matches) {
- $this->imports[] = $matches[0];
- return '';
- },
- $file
- );
+ $file = preg_replace_callback(self::CSS_IMPORT_REGEX, function ($matches) {
+ $this->imports[] = $matches[0];
+
+ return '';
+ }, $file);
return implode("\n", $this->imports) . "\n\n" . $file;
}
@@ -1101,17 +1125,10 @@ class Assets
*/
protected function rglob($directory, $pattern, $ltrim = null)
{
- $iterator = new RegexIterator(
- new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator(
- $directory,
- FilesystemIterator::SKIP_DOTS
- )
- ),
- $pattern
- );
+ $iterator = new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory,
+ FilesystemIterator::SKIP_DOTS)), $pattern);
$offset = strlen($ltrim);
- $files = array();
+ $files = [];
foreach ($iterator as $file) {
$files[] = substr($file->getPathname(), $offset);
@@ -1120,18 +1137,6 @@ class Assets
return $files;
}
- /**
- * Add all JavaScript assets within $directory.
- *
- * @param string $directory Relative to $this->public_dir
- *
- * @return $this
- */
- public function addDirJs($directory)
- {
- return $this->addDir($directory, self::JS_REGEX);
- }
-
/**
* Sets the state of CSS Pipeline
*
@@ -1139,7 +1144,7 @@ class Assets
*/
public function setCssPipeline($value)
{
- $this->css_pipeline = (bool) $value;
+ $this->css_pipeline = (bool)$value;
}
/**
@@ -1149,7 +1154,7 @@ class Assets
*/
public function setJsPipeline($value)
{
- $this->js_pipeline = (bool) $value;
+ $this->js_pipeline = (bool)$value;
}
/**
@@ -1159,9 +1164,12 @@ class Assets
*/
public function setTimestamp($value)
{
- $this->timestamp = '?'.$value;
+ $this->timestamp = '?' . $value;
}
+ /**
+ * @return string
+ */
public function __toString()
{
return '';
diff --git a/system/src/Grav/Common/Backup/ZipBackup.php b/system/src/Grav/Common/Backup/ZipBackup.php
index cf3689b28..a3dedc886 100644
--- a/system/src/Grav/Common/Backup/ZipBackup.php
+++ b/system/src/Grav/Common/Backup/ZipBackup.php
@@ -29,6 +29,14 @@ class ZipBackup
'.idea'
];
+ /**
+ * Backup
+ *
+ * @param null $destination
+ * @param callable|null $messager
+ *
+ * @return null|string
+ */
public static function backup($destination = null, callable $messager = null)
{
if (!$destination) {
diff --git a/system/src/Grav/Common/Browser.php b/system/src/Grav/Common/Browser.php
index 4feea462b..3272901d3 100644
--- a/system/src/Grav/Common/Browser.php
+++ b/system/src/Grav/Common/Browser.php
@@ -2,13 +2,20 @@
namespace Grav\Common;
/**
- * Simple wrapper for the very simple parse_user_agent() function
+ * Handles browser and platform versions
+ *
+ * Internally uses the PhpUserAgent package https://github.com/donatj/PhpUserAgent
+ *
+ * @author RocketTHeme
+ * @licence MIT
*/
class Browser
{
-
protected $useragent = [];
+ /**
+ * Browser constructor.
+ */
public function __construct()
{
try {
@@ -18,29 +25,99 @@ class Browser
}
}
+ /**
+ * Get the current browser identifier
+ *
+ * Currently detected browsers:
+ *
+ * Android Browser
+ * BlackBerry Browser
+ * Camino
+ * Kindle / Silk
+ * Firefox / Iceweasel
+ * Safari
+ * Internet Explorer
+ * IEMobile
+ * Chrome
+ * Opera
+ * Midori
+ * Vivaldi
+ * TizenBrowser
+ * Lynx
+ * Wget
+ * Curl
+ *
+ * @return string the lowercase browser name
+ */
public function getBrowser()
{
return strtolower($this->useragent['browser']);
}
+ /**
+ * Get the current platform identifier
+ *
+ * Currently detected platforms:
+ *
+ * Desktop
+ * -> Windows
+ * -> Linux
+ * -> Macintosh
+ * -> Chrome OS
+ * Mobile
+ * -> Android
+ * -> iPhone
+ * -> iPad / iPod Touch
+ * -> Windows Phone OS
+ * -> Kindle
+ * -> Kindle Fire
+ * -> BlackBerry
+ * -> Playbook
+ * -> Tizen
+ * Console
+ * -> Nintendo 3DS
+ * -> New Nintendo 3DS
+ * -> Nintendo Wii
+ * -> Nintendo WiiU
+ * -> PlayStation 3
+ * -> PlayStation 4
+ * -> PlayStation Vita
+ * -> Xbox 360
+ * -> Xbox One
+ *
+ * @return string the lowercase platform name
+ */
public function getPlatform()
{
return strtolower($this->useragent['platform']);
}
+ /**
+ * Get the current full version identifier
+ *
+ * @return string the browser full version identifier
+ */
public function getLongVersion()
{
return $this->useragent['version'];
}
+ /**
+ * Get the current major version identifier
+ *
+ * @return string the browser major version identifier
+ */
public function getVersion()
{
$version = explode('.', $this->getLongVersion());
+
return intval($version[0]);
}
/**
* Determine if the request comes from a human, or from a bot/crawler
+ *
+ * @return bool
*/
public function isHuman()
{
diff --git a/system/src/Grav/Common/Cache.php b/system/src/Grav/Common/Cache.php
index f7a6d4bae..e938c32b9 100644
--- a/system/src/Grav/Common/Cache.php
+++ b/system/src/Grav/Common/Cache.php
@@ -1,7 +1,7 @@
config->get('system.cache.prefix');
- $this->enabled = (bool) $this->config->get('system.cache.enabled');
+ $this->enabled = (bool)$this->config->get('system.cache.enabled');
// Cache key allows us to invalidate all cache on configuration changes.
- $this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION), 2, 8);
+ $this->key = ($prefix ? $prefix : 'g') . '-' . substr(md5($uri->rootUrl(true) . $this->config->key() . GRAV_VERSION),
+ 2, 8);
$this->driver_setting = $this->config->get('system.cache.driver');
@@ -127,7 +130,7 @@ class Cache extends Getters
* If there is no config option for $driver in the config, or it's set to 'auto', it will
* pick the best option based on which cache extensions are installed.
*
- * @return DoctrineCacheDriver The cache driver to use
+ * @return DoctrineCache\CacheProvider The cache driver to use
*/
public function getCacheDriver()
{
@@ -152,40 +155,40 @@ class Cache extends Getters
switch ($driver_name) {
case 'apc':
- $driver = new \Doctrine\Common\Cache\ApcCache();
+ $driver = new DoctrineCache\ApcCache();
break;
case 'apcu':
- $driver = new \Doctrine\Common\Cache\ApcuCache();
+ $driver = new DoctrineCache\ApcuCache();
break;
case 'wincache':
- $driver = new \Doctrine\Common\Cache\WinCacheCache();
+ $driver = new DoctrineCache\WinCacheCache();
break;
case 'xcache':
- $driver = new \Doctrine\Common\Cache\XcacheCache();
+ $driver = new DoctrineCache\XcacheCache();
break;
case 'memcache':
$memcache = new \Memcache();
- $memcache->connect($this->config->get('system.cache.memcache.server','localhost'),
- $this->config->get('system.cache.memcache.port', 11211));
- $driver = new \Doctrine\Common\Cache\MemcacheCache();
+ $memcache->connect($this->config->get('system.cache.memcache.server', 'localhost'),
+ $this->config->get('system.cache.memcache.port', 11211));
+ $driver = new DoctrineCache\MemcacheCache();
$driver->setMemcache($memcache);
break;
case 'redis':
$redis = new \Redis();
- $redis->connect($this->config->get('system.cache.redis.server','localhost'),
- $this->config->get('system.cache.redis.port', 6379));
+ $redis->connect($this->config->get('system.cache.redis.server', 'localhost'),
+ $this->config->get('system.cache.redis.port', 6379));
- $driver = new \Doctrine\Common\Cache\RedisCache();
+ $driver = new DoctrineCache\RedisCache();
$driver->setRedis($redis);
break;
default:
- $driver = new \Doctrine\Common\Cache\FilesystemCache($this->cache_dir);
+ $driver = new DoctrineCache\FilesystemCache($this->cache_dir);
break;
}
@@ -196,6 +199,7 @@ class Cache extends Getters
* Gets a cached entry if it exists based on an id. If it does not exist, it returns false
*
* @param string $id the id of the cached entry
+ *
* @return object returns the cached entry, can be any type, or false if doesn't exist
*/
public function fetch($id)
@@ -210,9 +214,9 @@ class Cache extends Getters
/**
* Stores a new cached entry.
*
- * @param string $id the id of the cached entry
+ * @param string $id the id of the cached entry
* @param array|object $data the data for the cached entry to store
- * @param int $lifetime the lifetime to store the entry in seconds
+ * @param int $lifetime the lifetime to store the entry in seconds
*/
public function save($id, $data, $lifetime = null)
{
@@ -235,7 +239,7 @@ class Cache extends Getters
/**
* Helper method to clear all Grav caches
*
- * @param string $remove standard|all|assets-only|images-only|cache-only
+ * @param string $remove standard|all|assets-only|images-only|cache-only
*
* @return array
*/
@@ -245,7 +249,7 @@ class Cache extends Getters
$output = [];
$user_config = USER_DIR . 'config/system.yaml';
- switch($remove) {
+ switch ($remove) {
case 'all':
$remove_paths = self::$all_remove;
break;
@@ -268,8 +272,9 @@ class Cache extends Getters
// Convert stream to a real path
$path = $locator->findResource($stream, true, true);
// Make sure path exists before proceeding, otherwise we would wipe ROOT_DIR
- if (!$path)
+ if (!$path) {
throw new \RuntimeException("Stream '{$stream}' not found", 500);
+ }
$anything = false;
$files = glob($path . '/*');
diff --git a/system/src/Grav/Common/Composer.php b/system/src/Grav/Common/Composer.php
index 5efde8912..804bc4c15 100644
--- a/system/src/Grav/Common/Composer.php
+++ b/system/src/Grav/Common/Composer.php
@@ -35,6 +35,11 @@ class Composer
return $path;
}
+ /**
+ * Return the composer executable file path
+ *
+ * @return string
+ */
public static function getComposerExecutor()
{
$executor = PHP_BINARY . ' ';
diff --git a/system/src/Grav/Common/Data/Validation.php b/system/src/Grav/Common/Data/Validation.php
index 9387effba..f8e0c3119 100644
--- a/system/src/Grav/Common/Data/Validation.php
+++ b/system/src/Grav/Common/Data/Validation.php
@@ -559,6 +559,10 @@ class Validation
$options = isset($field['options']) ? array_keys($field['options']) : array();
$multi = isset($field['multiple']) ? $field['multiple'] : false;
+ if (count($values) == 1 && isset($values[0]) && $values[0] == '') {
+ return null;
+ }
+
if ($options) {
$useKey = isset($field['use']) && $field['use'] == 'keys';
foreach ($values as $key => $value) {
diff --git a/system/src/Grav/Common/Debugger.php b/system/src/Grav/Common/Debugger.php
index 64824ff69..219fa6a1c 100644
--- a/system/src/Grav/Common/Debugger.php
+++ b/system/src/Grav/Common/Debugger.php
@@ -1,8 +1,10 @@
debugbar = new StandardDebugBar();
$this->debugbar['time']->addMeasure('Loading', $this->debugbar['time']->getRequestStartTime(), microtime(true));
}
+ /**
+ * Initialize the debugger
+ *
+ * @return $this
+ * @throws \DebugBar\DebugBarException
+ */
public function init()
{
$this->grav = Grav::instance();
+ $this->config = $this->grav['config'];
if ($this->enabled()) {
- $this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('system'), 'Config'));
- $this->debugbar->addCollector(new \DebugBar\DataCollector\ConfigCollector((array)$this->grav['config']->get('plugins'), 'Plugins'));
+ $this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('system'), 'Config'));
+ $this->debugbar->addCollector(new ConfigCollector((array)$this->config->get('plugins'), 'Plugins'));
}
+
return $this;
}
+ /**
+ * Set/get the enabled state of the debugger
+ *
+ * @param bool $state If null, the method returns the enabled value. If set, the method sets the enabled state
+ *
+ * @return null
+ */
public function enabled($state = null)
{
if (isset($state)) {
$this->enabled = $state;
} else {
if (!isset($this->enabled)) {
- $this->enabled = $this->grav['config']->get('system.debugger.enabled');
+ $this->enabled = $this->config->get('system.debugger.enabled');
}
}
+
return $this->enabled;
}
+ /**
+ * Add the debugger assets to the Grav Assets
+ *
+ * @return $this
+ */
public function addAssets()
{
if ($this->enabled()) {
+ /** @var Assets $assets */
$assets = $this->grav['assets'];
// Add jquery library
@@ -69,58 +105,113 @@ class Debugger
$assets->addJs($js);
}
}
+
return $this;
}
+ /**
+ * Adds a data collector
+ *
+ * @param $collector
+ *
+ * @return $this
+ * @throws \DebugBar\DebugBarException
+ */
public function addCollector($collector)
{
$this->debugbar->addCollector($collector);
+
return $this;
}
+ /**
+ * Returns a data collector
+ *
+ * @param $collector
+ *
+ * @return \DebugBar\DataCollector\DataCollectorInterface
+ * @throws \DebugBar\DebugBarException
+ */
public function getCollector($collector)
{
return $this->debugbar->getCollector($collector);
}
+ /**
+ * Displays the debug bar
+ *
+ * @return $this
+ */
public function render()
{
if ($this->enabled()) {
echo $this->renderer->render();
}
+
return $this;
}
+ /**
+ * Sends the data through the HTTP headers
+ *
+ * @return $this
+ */
public function sendDataInHeaders()
{
$this->debugbar->sendDataInHeaders();
+
return $this;
}
+ /**
+ * Start a timer with an associated name and description
+ *
+ * @param $name
+ * @param string|null $description
+ *
+ * @return $this
+ */
public function startTimer($name, $description = null)
{
- if ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled')) {
+ if ($name[0] == '_' || $this->config->get('system.debugger.enabled')) {
$this->debugbar['time']->startMeasure($name, $description);
$this->timers[] = $name;
}
+
return $this;
}
+ /**
+ * Stop the named timer
+ *
+ * @param string $name
+ *
+ * @return $this
+ */
public function stopTimer($name)
{
- if (in_array($name, $this->timers) && ($name[0] == '_' || $this->grav['config']->get('system.debugger.enabled'))) {
+ if (in_array($name, $this->timers) && ($name[0] == '_' || $this->config->get('system.debugger.enabled'))) {
$this->debugbar['time']->stopMeasure($name);
}
return $this;
}
-
+ /**
+ * Dump variables into the Messages tab of the Debug Bar
+ *
+ * @param $message
+ * @param string $label
+ * @param bool $isString
+ *
+ * @return $this
+ */
public function addMessage($message, $label = 'info', $isString = true)
{
if ($this->enabled()) {
$this->debugbar['messages']->addMessage($message, $label, $isString);
}
+
return $this;
}
}
diff --git a/system/src/Grav/Common/Errors/Errors.php b/system/src/Grav/Common/Errors/Errors.php
index b8575fb06..f656e4a94 100644
--- a/system/src/Grav/Common/Errors/Errors.php
+++ b/system/src/Grav/Common/Errors/Errors.php
@@ -30,11 +30,15 @@ class Errors
}
}
- if (function_exists('Whoops\isAjaxRequest')) { //Whoops 2
+ if (method_exists('Whoops\Util\Misc', 'isAjaxRequest')) { //Whoops 2.0
+ if (Whoops\Util\Misc::isAjaxRequest()) {
+ $whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
+ }
+ } elseif (function_exists('Whoops\isAjaxRequest')) { //Whoops 2.0.0-alpha
if (Whoops\isAjaxRequest()) {
$whoops->pushHandler(new Whoops\Handler\JsonResponseHandler);
}
- } else { //Whoops 1
+ } else { //Whoops 1.x
$json_page = new Whoops\Handler\JsonResponseHandler;
$json_page->onlyForAjaxRequests(true);
}
diff --git a/system/src/Grav/Common/Filesystem/Folder.php b/system/src/Grav/Common/Filesystem/Folder.php
index 81d610898..26e90fe31 100644
--- a/system/src/Grav/Common/Filesystem/Folder.php
+++ b/system/src/Grav/Common/Filesystem/Folder.php
@@ -64,8 +64,9 @@ abstract class Folder
/**
* Get relative path between target and base path. If path isn't relative, return full path.
*
- * @param string $path
- * @param string $base
+ * @param string $path
+ * @param mixed|string $base
+ *
* @return string
*/
public static function getRelativePath($path, $base = GRAV_ROOT)
@@ -141,7 +142,7 @@ abstract class Folder
* @return array
* @throws \RuntimeException
*/
- public static function all($path, array $params = array())
+ public static function all($path, array $params = [])
{
if ($path === false) {
throw new \RuntimeException("Path to {$path} doesn't exist.");
@@ -166,7 +167,7 @@ abstract class Folder
$iterator = new \FilesystemIterator($path);
}
- $results = array();
+ $results = [];
/** @var \RecursiveDirectoryIterator $file */
foreach ($iterator as $file) {
diff --git a/system/src/Grav/Common/Filesystem/RecursiveFolderFilterIterator.php b/system/src/Grav/Common/Filesystem/RecursiveFolderFilterIterator.php
index aa9fd4a84..a84a51906 100644
--- a/system/src/Grav/Common/Filesystem/RecursiveFolderFilterIterator.php
+++ b/system/src/Grav/Common/Filesystem/RecursiveFolderFilterIterator.php
@@ -3,12 +3,21 @@ namespace Grav\Common\Filesystem;
use Grav\Common\GravTrait;
+/**
+ * Class RecursiveFolderFilterIterator
+ * @package Grav\Common\Filesystem
+ */
class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
{
use GravTrait;
protected static $folder_ignores;
+ /**
+ * Create a RecursiveFilterIterator from a RecursiveIterator
+ *
+ * @param RecursiveIterator $iterator
+ */
public function __construct(\RecursiveIterator $iterator)
{
parent::__construct($iterator);
@@ -17,9 +26,13 @@ class RecursiveFolderFilterIterator extends \RecursiveFilterIterator
}
}
+ /**
+ * Check whether the current element of the iterator is acceptable
+ *
+ * @return bool true if the current element is acceptable, otherwise false.
+ */
public function accept()
{
-
/** @var $current \SplFileInfo */
$current = $this->current();
diff --git a/system/src/Grav/Common/GPM/Response.php b/system/src/Grav/Common/GPM/Response.php
index 87ba44e9b..578b5c3fc 100644
--- a/system/src/Grav/Common/GPM/Response.php
+++ b/system/src/Grav/Common/GPM/Response.php
@@ -2,9 +2,12 @@
namespace Grav\Common\GPM;
use Grav\Common\Utils;
+use Grav\Common\GravTrait;
class Response
{
+ use GravTrait;
+
/**
* The callback for the progress
*
@@ -192,6 +195,12 @@ class Response
$options = $args[1];
$callback = $args[2];
+ // if proxy set add that
+ $proxy_url = self::getGrav()['config']->get('system.proxy_url');
+ if ($proxy_url) {
+ $options['fopen']['proxy'] = $proxy_url;
+ }
+
if ($callback) {
$options['fopen']['notification'] = ['self', 'progress'];
}
@@ -246,6 +255,12 @@ class Response
);
}
+ // if proxy set add that
+ $proxy_url = self::getGrav()['config']->get('system.proxy_url');
+ if ($proxy_url) {
+ $options['curl'][CURLOPT_PROXY] = $proxy_url;
+ }
+
// no open_basedir set, we can proceed normally
if (!ini_get('open_basedir')) {
curl_setopt_array($ch, $options['curl']);
diff --git a/system/src/Grav/Common/Getters.php b/system/src/Grav/Common/Getters.php
index 857dccaba..8db51d324 100644
--- a/system/src/Grav/Common/Getters.php
+++ b/system/src/Grav/Common/Getters.php
@@ -5,7 +5,7 @@ namespace Grav\Common;
* Abstract class to implement magic __get(), __set(), __isset() and __unset().
* Also implements ArrayAccess.
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
abstract class Getters implements \ArrayAccess, \Countable
@@ -32,6 +32,7 @@ abstract class Getters implements \ArrayAccess, \Countable
* Magic getter method
*
* @param mixed $offset Medium name value
+ *
* @return mixed Medium value
*/
public function __get($offset)
@@ -42,7 +43,8 @@ abstract class Getters implements \ArrayAccess, \Countable
/**
* Magic method to determine if the attribute is set
*
- * @param mixed $offset Medium name value
+ * @param mixed $offset Medium name value
+ *
* @return boolean True if the value is set
*/
public function __isset($offset)
@@ -62,12 +64,14 @@ abstract class Getters implements \ArrayAccess, \Countable
/**
* @param mixed $offset
+ *
* @return bool
*/
public function offsetExists($offset)
{
if ($this->gettersVariable) {
$var = $this->gettersVariable;
+
return isset($this->{$var}[$offset]);
} else {
return isset($this->{$offset});
@@ -76,12 +80,14 @@ abstract class Getters implements \ArrayAccess, \Countable
/**
* @param mixed $offset
+ *
* @return mixed
*/
public function offsetGet($offset)
{
if ($this->gettersVariable) {
$var = $this->gettersVariable;
+
return isset($this->{$var}[$offset]) ? $this->{$var}[$offset] : null;
} else {
return isset($this->{$offset}) ? $this->{$offset} : null;
@@ -137,13 +143,17 @@ abstract class Getters implements \ArrayAccess, \Countable
{
if ($this->gettersVariable) {
$var = $this->gettersVariable;
+
return $this->{$var};
} else {
- $properties = (array) $this;
- $list = array();
+ $properties = (array)$this;
+ $list = [];
foreach ($properties as $property => $value) {
- if ($property[0] != "\0") $list[$property] = $value;
+ if ($property[0] != "\0") {
+ $list[$property] = $value;
+ }
}
+
return $list;
}
}
diff --git a/system/src/Grav/Common/Grav.php b/system/src/Grav/Common/Grav.php
index 1642211d2..05cc8944e 100644
--- a/system/src/Grav/Common/Grav.php
+++ b/system/src/Grav/Common/Grav.php
@@ -1,8 +1,11 @@
register(new ErrorServiceProvider);
$container['uri'] = function ($c) {
+ /** @var Grav $c */
return new Uri($c);
};
$container['task'] = function ($c) {
+ /** @var Grav $c */
return !empty($_POST['task']) ? $_POST['task'] : $c['uri']->param('task');
};
- $container['events'] = function ($c) {
+ $container['events'] = function () {
return new EventDispatcher;
};
$container['cache'] = function ($c) {
+ /** @var Grav $c */
return new Cache($c);
};
$container['session'] = function ($c) {
+ /** @var Grav $c */
return new Session($c);
};
- $container['plugins'] = function ($c) {
+ $container['plugins'] = function () {
return new Plugins();
};
$container['themes'] = function ($c) {
+ /** @var Grav $c */
return new Themes($c);
};
$container['twig'] = function ($c) {
+ /** @var Grav $c */
return new Twig($c);
};
$container['taxonomy'] = function ($c) {
+ /** @var Grav $c */
return new Taxonomy($c);
};
$container['language'] = function ($c) {
+ /** @var Grav $c */
return new Language($c);
};
$container['pages'] = function ($c) {
- return new Page\Pages($c);
+ /** @var Grav $c */
+ return new Pages($c);
};
$container['assets'] = new Assets();
$container['page'] = function ($c) {
+ /** @var Grav $c */
+
/** @var Pages $pages */
$pages = $c['pages'];
/** @var Language $language */
@@ -138,7 +166,7 @@ class Grav extends Container
if (!$page || !$page->routable()) {
// Try fallback URL stuff...
- $c->fallbackUrl($page, $path);
+ $c->fallbackUrl($path);
// If no page found, fire event
$event = $c->fireEvent('onPageNotFound');
@@ -149,22 +177,31 @@ class Grav extends Container
throw new \RuntimeException('Page Not Found', 404);
}
}
+
return $page;
};
+
$container['output'] = function ($c) {
+ /** @var Grav $c */
return $c['twig']->processSite($c['uri']->extension());
};
- $container['browser'] = function ($c) {
+
+ $container['browser'] = function () {
return new Browser();
};
$container['base_url_absolute'] = function ($c) {
+ /** @var Grav $c */
return $c['config']->get('system.base_url_absolute') ?: $c['uri']->rootUrl(true);
};
+
$container['base_url_relative'] = function ($c) {
+ /** @var Grav $c */
return $c['config']->get('system.base_url_relative') ?: $c['uri']->rootUrl(false);
};
+
$container['base_url'] = function ($c) {
+ /** @var Grav $c */
return $c['config']->get('system.absolute_urls') ? $c['base_url_absolute'] : $c['base_url_relative'];
};
@@ -178,6 +215,9 @@ class Grav extends Container
return $container;
}
+ /**
+ * Process a request
+ */
public function process()
{
/** @var Debugger $debugger */
@@ -206,7 +246,7 @@ class Grav extends Container
ob_start();
if ($this['config']->get('system.cache.gzip')) {
// Enable zip/deflate with a fallback in case of if browser does not support compressing.
- if(!ob_start("ob_gzhandler")) {
+ if (!ob_start("ob_gzhandler")) {
ob_start();
}
}
@@ -278,7 +318,7 @@ class Grav extends Container
* Redirect browser to another location.
*
* @param string $route Internal route.
- * @param int $code Redirection code (30x)
+ * @param int $code Redirection code (30x)
*/
public function redirect($route, $code = null)
{
@@ -304,10 +344,13 @@ class Grav extends Container
if ($uri->isExternal($route)) {
$url = $route;
} else {
- if ($this['config']->get('system.pages.redirect_trailing_slash', true))
- $url = rtrim($uri->rootUrl(), '/') .'/'. trim($route, '/'); // Remove trailing slash
- else
- $url = rtrim($uri->rootUrl(), '/') .'/'. ltrim($route, '/'); // Support trailing slash default routes
+ $url = rtrim($uri->rootUrl(), '/') . '/';
+
+ if ($this['config']->get('system.pages.redirect_trailing_slash', true)) {
+ $url .= trim($route, '/'); // Remove trailing slash
+ } else {
+ $url .= ltrim($route, '/'); // Support trailing slash default routes
+ }
}
header("Location: {$url}", true, $code);
@@ -318,7 +361,7 @@ class Grav extends Container
* Redirect browser to another location taking language into account (preferred)
*
* @param string $route Internal route.
- * @param int $code Redirection code (30x)
+ * @param int $code Redirection code (30x)
*/
public function redirectLangSafe($route, $code = null)
{
@@ -326,9 +369,9 @@ class Grav extends Container
$language = $this['language'];
if (!$this['uri']->isExternal($route) && $language->enabled() && $language->isIncludeDefaultLanguage()) {
- return $this->redirect($language->getLanguage() . $route, $code);
+ $this->redirect($language->getLanguage() . $route, $code);
} else {
- return $this->redirect($route, $code);
+ $this->redirect($route, $code);
}
}
@@ -336,6 +379,7 @@ class Grav extends Container
* Returns mime type for the file format.
*
* @param string $format
+ *
* @return string
*/
public function mime($format)
@@ -352,6 +396,7 @@ class Grav extends Container
case 'xml':
return 'application/xml';
}
+
return 'text/html';
}
@@ -373,7 +418,7 @@ class Grav extends Container
if ($expires > 0) {
$expires_date = gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT';
header('Cache-Control: max-age=' . $expires);
- header('Expires: '. $expires_date);
+ header('Expires: ' . $expires_date);
}
// Set the last modified time
@@ -408,12 +453,14 @@ class Grav extends Container
*
* @param string $eventName
* @param Event $event
+ *
* @return Event
*/
public function fireEvent($eventName, Event $event = null)
{
/** @var EventDispatcher $events */
$events = $this['events'];
+
return $events->dispatch($eventName, $event);
}
@@ -471,10 +518,10 @@ class Grav extends Container
/**
* This attempts to find media, other files, and download them
- * @param $page
+ *
* @param $path
*/
- protected function fallbackUrl($page, $path)
+ protected function fallbackUrl($path)
{
/** @var Uri $uri */
$uri = $this['uri'];
@@ -494,20 +541,22 @@ class Grav extends Container
}
$path_parts = pathinfo($path);
+
+ /** @var Page $page */
$page = $this['pages']->dispatch($path_parts['dirname'], true);
+
if ($page) {
$media = $page->media()->all();
-
$parsed_url = parse_url(rawurldecode($uri->basename()));
-
$media_file = $parsed_url['path'];
// if this is a media object, try actions first
if (isset($media[$media_file])) {
+ /** @var Medium $medium */
$medium = $media[$media_file];
foreach ($uri->query(null, true) as $action => $params) {
if (in_array($action, ImageMedium::$magic_actions)) {
- call_user_func_array(array(&$medium, $action), explode(',', $params));
+ call_user_func_array([&$medium, $action], explode(',', $params));
}
}
Utils::download($medium->path(), false);
diff --git a/system/src/Grav/Common/GravTrait.php b/system/src/Grav/Common/GravTrait.php
index 171017363..a8f86826c 100644
--- a/system/src/Grav/Common/GravTrait.php
+++ b/system/src/Grav/Common/GravTrait.php
@@ -1,6 +1,11 @@
init();
@@ -58,14 +59,14 @@ class Inflector
$lowercased_word = strtolower($word);
foreach ($this->uncountable as $_uncountable) {
- if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
+ if (substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($this->irregular as $_plural => $_singular) {
- if (preg_match('/('.$_plural.')$/i', $word, $arr)) {
- return preg_replace('/('.$_plural.')$/i', substr($arr[0], 0, 1).substr($_singular, 1), $word);
+ if (preg_match('/(' . $_plural . ')$/i', $word, $arr)) {
+ return preg_replace('/(' . $_plural . ')$/i', substr($arr[0], 0, 1) . substr($_singular, 1), $word);
}
}
@@ -74,17 +75,19 @@ class Inflector
return preg_replace($rule, $replacement, $word);
}
}
+
return false;
}
/**
- * Singularizes English nouns.
- *
- * @param string $word English noun to singularize
- * @param int $count
- * @return string Singular noun.
- */
+ * Singularizes English nouns.
+ *
+ * @param string $word English noun to singularize
+ * @param int $count
+ *
+ * @return string Singular noun.
+ */
public function singularize($word, $count = 1)
{
$this->init();
@@ -95,14 +98,14 @@ class Inflector
$lowercased_word = strtolower($word);
foreach ($this->uncountable as $_uncountable) {
- if (substr($lowercased_word, (-1*strlen($_uncountable))) == $_uncountable) {
+ if (substr($lowercased_word, (-1 * strlen($_uncountable))) == $_uncountable) {
return $word;
}
}
foreach ($this->irregular as $_plural => $_singular) {
- if (preg_match('/('.$_singular.')$/i', $word, $arr)) {
- return preg_replace('/('.$_singular.')$/i', substr($arr[0], 0, 1).substr($_plural, 1), $word);
+ if (preg_match('/(' . $_singular . ')$/i', $word, $arr)) {
+ return preg_replace('/(' . $_singular . ')$/i', substr($arr[0], 0, 1) . substr($_plural, 1), $word);
}
}
@@ -116,181 +119,206 @@ class Inflector
}
/**
- * Converts an underscored or CamelCase word into a English
- * sentence.
- *
- * The titleize public function converts text like "WelcomePage",
- * "welcome_page" or "welcome page" to this "Welcome
- * Page".
- * If second parameter is set to 'first' it will only
- * capitalize the first character of the title.
- *
- * @param string $word Word to format as tile
- * @param string $uppercase If set to 'first' it will only uppercase the
- * first character. Otherwise it will uppercase all
- * the words in the title.
- * @return string Text formatted as title
- */
+ * Converts an underscored or CamelCase word into a English
+ * sentence.
+ *
+ * The titleize public function converts text like "WelcomePage",
+ * "welcome_page" or "welcome page" to this "Welcome
+ * Page".
+ * If second parameter is set to 'first' it will only
+ * capitalize the first character of the title.
+ *
+ * @param string $word Word to format as tile
+ * @param string $uppercase If set to 'first' it will only uppercase the
+ * first character. Otherwise it will uppercase all
+ * the words in the title.
+ *
+ * @return string Text formatted as title
+ */
public function titleize($word, $uppercase = '')
{
$uppercase = $uppercase == 'first' ? 'ucfirst' : 'ucwords';
+
return $uppercase($this->humanize($this->underscorize($word)));
}
/**
- * Returns given word as CamelCased
- *
- * Converts a word like "send_email" to "SendEmail". It
- * will remove non alphanumeric character from the word, so
- * "who's online" will be converted to "WhoSOnline"
- *
- * @see variablize
- * @param string $word Word to convert to camel case
- * @return string UpperCamelCasedWord
- */
+ * Returns given word as CamelCased
+ *
+ * Converts a word like "send_email" to "SendEmail". It
+ * will remove non alphanumeric character from the word, so
+ * "who's online" will be converted to "WhoSOnline"
+ *
+ * @see variablize
+ *
+ * @param string $word Word to convert to camel case
+ *
+ * @return string UpperCamelCasedWord
+ */
public function camelize($word)
{
return str_replace(' ', '', ucwords(preg_replace('/[^A-Z^a-z^0-9]+/', ' ', $word)));
}
/**
- * Converts a word "into_it_s_underscored_version"
- *
- * Convert any "CamelCased" or "ordinary Word" into an
- * "underscored_word".
- *
- * This can be really useful for creating friendly URLs.
- *
- * @param string $word Word to underscore
- * @return string Underscored word
- */
+ * Converts a word "into_it_s_underscored_version"
+ *
+ * Convert any "CamelCased" or "ordinary Word" into an
+ * "underscored_word".
+ *
+ * This can be really useful for creating friendly URLs.
+ *
+ * @param string $word Word to underscore
+ *
+ * @return string Underscored word
+ */
public function underscorize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1_\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1_\2', $regex1);
$regex3 = preg_replace('/[^A-Z^a-z^0-9]+/', '_', $regex2);
- return strtolower($regex3);
+
+ return strtolower($regex3);
}
/**
- * Converts a word "into-it-s-hyphenated-version"
- *
- * Convert any "CamelCased" or "ordinary Word" into an
- * "hyphenated-word".
- *
- * This can be really useful for creating friendly URLs.
- *
- * @param string $word Word to hyphenate
- * @return string hyphenized word
- */
+ * Converts a word "into-it-s-hyphenated-version"
+ *
+ * Convert any "CamelCased" or "ordinary Word" into an
+ * "hyphenated-word".
+ *
+ * This can be really useful for creating friendly URLs.
+ *
+ * @param string $word Word to hyphenate
+ *
+ * @return string hyphenized word
+ */
public function hyphenize($word)
{
$regex1 = preg_replace('/([A-Z]+)([A-Z][a-z])/', '\1-\2', $word);
$regex2 = preg_replace('/([a-zd])([A-Z])/', '\1-\2', $regex1);
$regex3 = preg_replace('/[^A-Z^a-z^0-9]+/', '-', $regex2);
- return strtolower($regex3);
+
+ return strtolower($regex3);
}
/**
- * Returns a human-readable string from $word
- *
- * Returns a human-readable string from $word, by replacing
- * underscores with a space, and by upper-casing the initial
- * character by default.
- *
- * If you need to uppercase all the words you just have to
- * pass 'all' as a second parameter.
- *
- * @param string $word String to "humanize"
- * @param string $uppercase If set to 'all' it will uppercase all the words
- * instead of just the first one.
- * @return string Human-readable word
- */
+ * Returns a human-readable string from $word
+ *
+ * Returns a human-readable string from $word, by replacing
+ * underscores with a space, and by upper-casing the initial
+ * character by default.
+ *
+ * If you need to uppercase all the words you just have to
+ * pass 'all' as a second parameter.
+ *
+ * @param string $word String to "humanize"
+ * @param string $uppercase If set to 'all' it will uppercase all the words
+ * instead of just the first one.
+ *
+ * @return string Human-readable word
+ */
public function humanize($word, $uppercase = '')
{
$uppercase = $uppercase == 'all' ? 'ucwords' : 'ucfirst';
+
return $uppercase(str_replace('_', ' ', preg_replace('/_id$/', '', $word)));
}
/**
- * Same as camelize but first char is underscored
- *
- * Converts a word like "send_email" to "sendEmail". It
- * will remove non alphanumeric character from the word, so
- * "who's online" will be converted to "whoSOnline"
- *
- * @see camelize
- * @param string $word Word to lowerCamelCase
- * @return string Returns a lowerCamelCasedWord
- */
+ * Same as camelize but first char is underscored
+ *
+ * Converts a word like "send_email" to "sendEmail". It
+ * will remove non alphanumeric character from the word, so
+ * "who's online" will be converted to "whoSOnline"
+ *
+ * @see camelize
+ *
+ * @param string $word Word to lowerCamelCase
+ *
+ * @return string Returns a lowerCamelCasedWord
+ */
public function variablize($word)
{
$word = $this->camelize($word);
- return strtolower($word[0]).substr($word, 1);
+
+ return strtolower($word[0]) . substr($word, 1);
}
/**
- * Converts a class name to its table name according to rails
- * naming conventions.
- *
- * Converts "Person" to "people"
- *
- * @see classify
- * @param string $class_name Class name for getting related table_name.
- * @return string plural_table_name
- */
+ * Converts a class name to its table name according to rails
+ * naming conventions.
+ *
+ * Converts "Person" to "people"
+ *
+ * @see classify
+ *
+ * @param string $class_name Class name for getting related table_name.
+ *
+ * @return string plural_table_name
+ */
public function tableize($class_name)
{
- return $this->pluralize($this->underscore($class_name));
+ return $this->pluralize($this->underscorize($class_name));
}
/**
- * Converts a table name to its class name according to rails
- * naming conventions.
- *
- * Converts "people" to "Person"
- *
- * @see tableize
- * @param string $table_name Table name for getting related ClassName.
- * @return string SingularClassName
- */
+ * Converts a table name to its class name according to rails
+ * naming conventions.
+ *
+ * Converts "people" to "Person"
+ *
+ * @see tableize
+ *
+ * @param string $table_name Table name for getting related ClassName.
+ *
+ * @return string SingularClassName
+ */
public function classify($table_name)
{
return $this->camelize($this->singularize($table_name));
}
/**
- * Converts number to its ordinal English form.
- *
- * This method converts 13 to 13th, 2 to 2nd ...
- *
- * @param integer $number Number to get its ordinal value
- * @return string Ordinal representation of given string.
- */
+ * Converts number to its ordinal English form.
+ *
+ * This method converts 13 to 13th, 2 to 2nd ...
+ *
+ * @param integer $number Number to get its ordinal value
+ *
+ * @return string Ordinal representation of given string.
+ */
public function ordinalize($number)
{
$this->init();
-
+
if (in_array(($number % 100), range(11, 13))) {
- return $number.$this->ordinals['default'];
+ return $number . $this->ordinals['default'];
} else {
switch (($number % 10)) {
case 1:
- return $number.$this->ordinals['first'];
+ return $number . $this->ordinals['first'];
break;
case 2:
- return $number.$this->ordinals['second'];
+ return $number . $this->ordinals['second'];
break;
case 3:
- return $number.$this->ordinals['third'];
+ return $number . $this->ordinals['third'];
break;
default:
- return $number.$this->ordinals['default'];
+ return $number . $this->ordinals['default'];
break;
}
}
}
+ /**
+ * Converts a number of days to a number of months
+ *
+ * @param int $days
+ *
+ * @return int
+ */
public function monthize($days)
{
$now = new \DateTime();
@@ -300,9 +328,9 @@ class Inflector
$diff = $end->add($duration)->diff($now);
- // handle years
+ // handle years
if ($diff->y > 0) {
- $diff->m = $diff->m + 12*$diff->y;
+ $diff->m = $diff->m + 12 * $diff->y;
}
return $diff->m;
diff --git a/system/src/Grav/Common/Iterator.php b/system/src/Grav/Common/Iterator.php
index 287b925ae..9afd9dbd0 100644
--- a/system/src/Grav/Common/Iterator.php
+++ b/system/src/Grav/Common/Iterator.php
@@ -26,6 +26,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*
* @param string $key
* @param mixed $args
+ *
* @return mixed
*/
public function __call($key, $args)
@@ -79,11 +80,13 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
* Return nth item.
*
* @param int $key
+ *
* @return mixed|bool
*/
public function nth($key)
{
$items = array_keys($this->items);
+
return (isset($items[$key])) ? $this->offsetGet($items[$key]) : false;
}
@@ -95,6 +98,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
public function first()
{
$items = array_keys($this->items);
+
return $this->offsetGet(array_shift($items));
}
@@ -106,6 +110,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
public function last()
{
$items = array_keys($this->items);
+
return $this->offsetGet(array_pop($items));
}
@@ -117,11 +122,13 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
public function reverse()
{
$this->items = array_reverse($this->items);
+
return $this;
}
/**
* @param mixed $needle Searched value.
+ *
* @return string|bool Key if found, otherwise false.
*/
public function indexOf($needle)
@@ -131,6 +138,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
return $key;
}
}
+
return false;
}
@@ -144,7 +152,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
$keys = array_keys($this->items);
shuffle($keys);
- $new = array();
+ $new = [];
foreach ($keys as $key) {
$new[$key] = $this->items[$key];
}
@@ -159,6 +167,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*
* @param int $offset
* @param int $length
+ *
* @return $this
*/
public function slice($offset, $length = null)
@@ -171,12 +180,13 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
/**
* Pick one or more random entries.
*
- * @param int $num Specifies how many entries should be picked.
+ * @param int $num Specifies how many entries should be picked.
+ *
* @return $this
*/
public function random($num = 1)
{
- $this->items = array_intersect_key($this->items, array_flip((array) array_rand($this->items, $num)));
+ $this->items = array_intersect_key($this->items, array_flip((array)array_rand($this->items, $num)));
return $this;
}
@@ -184,7 +194,8 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
/**
* Append new elements to the list.
*
- * @param array|Iterator $items Items to be appended. Existing keys will be overridden with the new values.
+ * @param array|Iterator $items Items to be appended. Existing keys will be overridden with the new values.
+ *
* @return $this
*/
public function append($items)
@@ -192,14 +203,17 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
if ($items instanceof static) {
$items = $items->toArray();
}
- $this->items = array_merge($this->items, (array) $items);
+ $this->items = array_merge($this->items, (array)$items);
return $this;
}
/**
* Filter elements from the list
- * @param callable|null $callback A function the receives ($value, $key) and must return a boolean to indicate filter status
+ *
+ * @param callable|null $callback A function the receives ($value, $key) and must return a boolean to indicate
+ * filter status
+ *
* @return $this
*/
public function filter(callable $callback = null)
@@ -207,7 +221,7 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
foreach ($this->items as $key => $value) {
if (
($callback && !call_user_func($callback, $value, $key)) ||
- (!$callback && !(bool) $value)
+ (!$callback && !(bool)$value)
) {
unset($this->items[$key]);
}
@@ -230,7 +244,9 @@ class Iterator implements \ArrayAccess, \Iterator, \Countable, \Serializable
*/
public function sort(callable $callback = null, $desc = false)
{
- if (!$callback || !is_callable($callback)) { return $this; }
+ if (!$callback || !is_callable($callback)) {
+ return $this;
+ }
$items = $this->items;
uasort($items, $callback);
diff --git a/system/src/Grav/Common/Language/Language.php b/system/src/Grav/Common/Language/Language.php
index 6a9e3f18c..eb69adcf1 100644
--- a/system/src/Grav/Common/Language/Language.php
+++ b/system/src/Grav/Common/Language/Language.php
@@ -252,6 +252,8 @@ class Language
/**
* Gets an array of valid extensions with active first, then fallback extensions
*
+ * @param string|null $file_ext
+ *
* @return array
*/
public function getFallbackPageExtensions($file_ext = null)
@@ -328,15 +330,15 @@ class Language
/**
* Translate a key and possibly arguments into a string using current lang and fallbacks
*
- * @param $args first argument is the lookup key value
- * other arguments can be passed and replaced in the translation with sprintf syntax
- * @param Array $languages
+ * @param mixed $args The first argument is the lookup key value
+ * Other arguments can be passed and replaced in the translation with sprintf syntax
+ * @param array $languages
* @param bool $array_support
* @param bool $html_out
*
* @return string
*/
- public function translate($args, Array $languages = null, $array_support = false, $html_out = false)
+ public function translate($args, array $languages = null, $array_support = false, $html_out = false)
{
if (is_array($args)) {
$lookup = array_shift($args);
@@ -345,7 +347,6 @@ class Language
$args = [];
}
-
if ($this->config->get('system.languages.translations', true)) {
if ($this->enabled() && $lookup) {
if (empty($languages)) {
@@ -422,8 +423,8 @@ class Language
/**
* Lookup the translation text for a given lang and key
*
- * @param $lang lang code
- * @param $key key to lookup with
+ * @param string $lang lang code
+ * @param string $key key to lookup with
* @param bool $array_support
*
* @return string
@@ -438,6 +439,13 @@ class Language
return $translation;
}
+ /**
+ * Get the browser accepted languages
+ *
+ * @param array $accept_langs
+ *
+ * @return array
+ */
public function getBrowserLanguages($accept_langs = [])
{
if (empty($this->http_accept_language)) {
@@ -451,9 +459,9 @@ class Language
// split $pref again by ';q='
// and decorate the language entries by inverted position
if (false !== ($i = strpos($pref, ';q='))) {
- $langs[substr($pref, 0, $i)] = array((float)substr($pref, $i + 3), -$k);
+ $langs[substr($pref, 0, $i)] = [(float)substr($pref, $i + 3), -$k];
} else {
- $langs[$pref] = array(1, -$k);
+ $langs[$pref] = [1, -$k];
}
}
arsort($langs);
diff --git a/system/src/Grav/Common/Markdown/Parsedown.php b/system/src/Grav/Common/Markdown/Parsedown.php
index f453a544a..95ead42d2 100644
--- a/system/src/Grav/Common/Markdown/Parsedown.php
+++ b/system/src/Grav/Common/Markdown/Parsedown.php
@@ -1,10 +1,20 @@
init($page, $defaults);
diff --git a/system/src/Grav/Common/Markdown/ParsedownExtra.php b/system/src/Grav/Common/Markdown/ParsedownExtra.php
index 526e5f905..515d1dc9c 100644
--- a/system/src/Grav/Common/Markdown/ParsedownExtra.php
+++ b/system/src/Grav/Common/Markdown/ParsedownExtra.php
@@ -1,10 +1,20 @@
page = $page;
$this->pages = $grav['pages'];
$this->BlockTypes['{'] [] = "TwigTag";
- $this->BlockTypes['['] [] = "ShortcodeTag";
$this->base_url = rtrim(self::getGrav()['base_url'] . self::getGrav()['pages']->base(), '/');
$this->pages_dir = self::getGrav()['locator']->findResource('page://');
- $this->special_chars = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
+ $this->special_chars = ['>' => 'gt', '<' => 'lt', '"' => 'quot'];
if ($defaults === null) {
$defaults = self::getGrav()['config']->get('system.pages.markdown');
@@ -60,7 +67,7 @@ trait ParsedownGravTrait
*/
public function addBlockType($type, $tag, $continuable = false, $completable = false)
{
- $this->BlockTypes[$type] []= $tag;
+ $this->BlockTypes[$type] [] = $tag;
if ($continuable) {
$this->continuable_blocks[] = $tag;
@@ -79,7 +86,7 @@ trait ParsedownGravTrait
*/
public function addInlineType($type, $tag)
{
- $this->InlineTypes[$type] []= $tag;
+ $this->InlineTypes[$type] [] = $tag;
$this->inlineMarkerList .= $type;
}
@@ -87,11 +94,13 @@ trait ParsedownGravTrait
* Overrides the default behavior to allow for plugin-provided blocks to be continuable
*
* @param $Type
+ *
* @return bool
*/
protected function isBlockContinuable($Type)
{
- $continuable = in_array($Type, $this->continuable_blocks) || method_exists($this, 'block'.$Type.'Continue');
+ $continuable = in_array($Type, $this->continuable_blocks) || method_exists($this, 'block' . $Type . 'Continue');
+
return $continuable;
}
@@ -99,11 +108,13 @@ trait ParsedownGravTrait
* Overrides the default behavior to allow for plugin-provided blocks to be completable
*
* @param $Type
+ *
* @return bool
*/
protected function isBlockCompletable($Type)
{
- $completable = in_array($Type, $this->completable_blocks) || method_exists($this, 'block'.$Type.'Complete');
+ $completable = in_array($Type, $this->completable_blocks) || method_exists($this, 'block' . $Type . 'Complete');
+
return $completable;
}
@@ -111,7 +122,8 @@ trait ParsedownGravTrait
/**
* Make the element function publicly accessible, Medium uses this to render from Twig
*
- * @param array $Element
+ * @param array $Element
+ *
* @return string markup
*/
public function elementToHtml(array $Element)
@@ -139,37 +151,28 @@ trait ParsedownGravTrait
protected function blockTwigTag($Line)
{
if (preg_match('/(?:{{|{%|{#)(.*)(?:}}|%}|#})/', $Line['body'], $matches)) {
- $Block = array(
+ $Block = [
'markup' => $Line['body'],
- );
- return $Block;
- }
- }
+ ];
- protected function blockShortcodeTag($Line)
- {
- if (preg_match('/^(?:\[)(.*)(?:\])$/', $Line['body'], $matches)) {
- $Block = array(
- 'markup' => $Line['body'],
- );
return $Block;
}
}
protected function inlineSpecialCharacter($Excerpt)
{
- if ($Excerpt['text'][0] === '&' && ! preg_match('/^?\w+;/', $Excerpt['text'])) {
- return array(
+ if ($Excerpt['text'][0] === '&' && !preg_match('/^?\w+;/', $Excerpt['text'])) {
+ return [
'markup' => '&',
'extent' => 1,
- );
+ ];
}
if (isset($this->special_chars[$Excerpt['text'][0]])) {
- return array(
- 'markup' => '&'.$this->special_chars[$Excerpt['text'][0]].';',
+ return [
+ 'markup' => '&' . $this->special_chars[$Excerpt['text'][0]] . ';',
'extent' => 1,
- );
+ ];
}
}
@@ -180,6 +183,7 @@ trait ParsedownGravTrait
$excerpt = parent::inlineImage($excerpt);
$excerpt['element']['attributes']['src'] = $matches[1];
$excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
+
return $excerpt;
} else {
$excerpt['type'] = 'image';
@@ -187,7 +191,7 @@ trait ParsedownGravTrait
}
// Some stuff we will need
- $actions = array();
+ $actions = [];
$media = null;
// if this is an image
@@ -229,7 +233,7 @@ trait ParsedownGravTrait
$actions = array_reduce(explode('&', $url['query']), function ($carry, $item) {
$parts = explode('=', $item, 2);
$value = isset($parts[1]) ? $parts[1] : null;
- $carry[] = [ 'method' => $parts[0], 'params' => $value ];
+ $carry[] = ['method' => $parts[0], 'params' => $value];
return $carry;
}, []);
@@ -237,7 +241,8 @@ trait ParsedownGravTrait
// loop through actions for the image and call them
foreach ($actions as $action) {
- $medium = call_user_func_array(array($medium, $action['method']), explode(',', urldecode($action['params'])));
+ $medium = call_user_func_array([$medium, $action['method']],
+ explode(',', urldecode($action['params'])));
}
if (isset($url['fragment'])) {
@@ -270,6 +275,7 @@ trait ParsedownGravTrait
$excerpt = parent::inlineLink($excerpt);
$excerpt['element']['attributes']['href'] = $matches[1];
$excerpt['extent'] = $excerpt['extent'] + strlen($matches[1]) - 1;
+
return $excerpt;
} else {
$excerpt = parent::inlineLink($excerpt);
@@ -312,7 +318,7 @@ trait ParsedownGravTrait
}
- $url['query']= http_build_query($actions, null, '&', PHP_QUERY_RFC3986);
+ $url['query'] = http_build_query($actions, null, '&', PHP_QUERY_RFC3986);
}
// if no query elements left, unset query
@@ -320,63 +326,15 @@ trait ParsedownGravTrait
unset ($url['query']);
}
- // set path to / if not set
- if (empty($url['path'])) {
- $url['path'] = '/';
- }
-
// if there is no scheme, the file is local and we'll need to convert that URL
if (!isset($url['scheme']) && (count($url) > 0)) {
- $url['path'] = Uri::convertUrl($this->page, $url['path'], $type, true);
+ $excerpt['element']['attributes']['href'] = Uri::convertUrl($this->page, Uri::buildUrl($url), $type,
+ true);
+ } elseif (in_array($url['scheme'], $this->special_protocols)) {
+ return $excerpt;
+ } else {
+ $excerpt['element']['attributes']['href'] = Uri::buildUrl($url);
}
-
- // if absolute urls enabled, add them
- if (self::getGrav()['config']->get('system.absolute_urls', false)) {
- $uri = self::getGrav()['uri'];
- $url['scheme'] = str_replace('://', '', $uri->scheme());
- $url['host'] = $uri->host();
-
- if ($uri->port() != 80 && $uri->port() != 443) {
- $url['port'] = $uri->port();
- }
-
- // check if page exists for this route, and if so, check if it has SSL enabled
- $pages = self::getGrav()['pages'];
- $routes = $pages->routes();
-
- // if this is an image, get the proper path
- $url_bits = pathinfo($url['path']);
- if (isset($url_bits['extension'])) {
- $target_path = $url_bits['dirname'];
- } else {
- $target_path = $url['path'];
- }
-
- // strip base from this path
- $target_path = str_replace($uri->rootUrl(), '', $target_path);
-
- // set to / if root
- if (empty($target_path)) {
- $target_path = '/';
- }
-
- // look to see if this page exists and has ssl enabled
- if (isset($routes[$target_path])) {
- $target_page = $pages->get($routes[$target_path]);
- if ($target_page) {
- $ssl_enabled = $target_page->ssl();
- if (isset($ssl_enabled)) {
- if ($ssl_enabled) {
- $url['scheme'] = 'https';
- } else {
- $url['scheme'] = 'http';
- }
- }
- }
- }
- }
-
- $excerpt['element']['attributes']['href'] = Uri::buildUrl($url);
}
return $excerpt;
@@ -387,6 +345,7 @@ trait ParsedownGravTrait
{
if (isset($this->$method) === true) {
$func = $this->$method;
+
return call_user_func_array($func, $args);
}
}
diff --git a/system/src/Grav/Common/Page/Collection.php b/system/src/Grav/Common/Page/Collection.php
index cc1593c28..861f55b74 100644
--- a/system/src/Grav/Common/Page/Collection.php
+++ b/system/src/Grav/Common/Page/Collection.php
@@ -8,7 +8,7 @@ use Grav\Common\Utils;
/**
* Collection of Pages.
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Collection extends Iterator
@@ -23,7 +23,14 @@ class Collection extends Iterator
*/
protected $params;
- public function __construct($items = array(), array $params = array(), Pages $pages = null)
+ /**
+ * Collection constructor.
+ *
+ * @param array $items
+ * @param array $params
+ * @param Pages|null $pages
+ */
+ public function __construct($items = [], array $params = [], Pages $pages = null)
{
parent::__construct($items);
@@ -31,6 +38,11 @@ class Collection extends Iterator
$this->pages = $pages ? $pages : Grav::instance()->offsetGet('pages');
}
+ /**
+ * Get the collection params
+ *
+ * @return array
+ */
public function params()
{
return $this->params;
@@ -40,11 +52,13 @@ class Collection extends Iterator
* Add a single page to a collection
*
* @param Page $page
+ *
* @return $this
*/
public function addPage(Page $page)
{
$this->items[$page->path()] = ['slug' => $page->slug()];
+
return $this;
}
@@ -63,11 +77,13 @@ class Collection extends Iterator
* Set parameters to the Collection
*
* @param array $params
+ *
* @return $this
*/
public function setParams(array $params)
{
$this->params = array_merge($this->params, $params);
+
return $this;
}
@@ -79,6 +95,7 @@ class Collection extends Iterator
public function current()
{
$current = parent::key();
+
return $this->pages->get($current);
}
@@ -90,13 +107,15 @@ class Collection extends Iterator
public function key()
{
$current = parent::current();
+
return $current['slug'];
}
/**
* Returns the value at specified offset.
*
- * @param mixed $offset The offset to retrieve.
+ * @param mixed $offset The offset to retrieve.
+ *
* @return mixed Can return all value types.
*/
public function offsetGet($offset)
@@ -108,6 +127,7 @@ class Collection extends Iterator
* Remove item from the list.
*
* @param Page|string|null $key
+ *
* @return $this|void
* @throws \InvalidArgumentException
*/
@@ -123,6 +143,7 @@ class Collection extends Iterator
}
parent::remove($key);
+
return $this;
}
@@ -132,6 +153,7 @@ class Collection extends Iterator
* @param string $by
* @param string $dir
* @param array $manual
+ *
* @return $this
*/
public function order($by, $dir = 'asc', $manual = null)
@@ -145,6 +167,7 @@ class Collection extends Iterator
* Check to see if this item is the first in the collection.
*
* @param string $path
+ *
* @return boolean True if item is first.
*/
public function isFirst($path)
@@ -160,11 +183,12 @@ class Collection extends Iterator
* Check to see if this item is the last in the collection.
*
* @param string $path
+ *
* @return boolean True if item is last.
*/
public function isLast($path)
{
- if ($this->items && $path == array_keys($this->items)[count($this->items)-1]) {
+ if ($this->items && $path == array_keys($this->items)[count($this->items) - 1]) {
return true;
} else {
return false;
@@ -174,7 +198,8 @@ class Collection extends Iterator
/**
* Gets the previous sibling based on current position.
*
- * @param string $path
+ * @param string $path
+ *
* @return Page The previous item.
*/
public function prevSibling($path)
@@ -185,7 +210,8 @@ class Collection extends Iterator
/**
* Gets the next sibling based on current position.
*
- * @param string $path
+ * @param string $path
+ *
* @return Page The next item.
*/
public function nextSibling($path)
@@ -198,6 +224,7 @@ class Collection extends Iterator
*
* @param string $path
* @param integer $direction either -1 or +1
+ *
* @return Page The sibling item.
*/
public function adjacentSibling($path, $direction = 1)
@@ -210,6 +237,7 @@ class Collection extends Iterator
return isset($values[$index]) ? $this->offsetGet($values[$index]) : $this;
}
+
return $this;
}
@@ -217,7 +245,8 @@ class Collection extends Iterator
/**
* Returns the item in the current position.
*
- * @param string $path the path the item
+ * @param string $path the path the item
+ *
* @return Page Item in the array the the current position.
*/
public function currentPosition($path)
@@ -256,6 +285,7 @@ class Collection extends Iterator
}
}
$this->items = $date_range;
+
return $this;
}
@@ -275,6 +305,7 @@ class Collection extends Iterator
}
}
$this->items = $visible;
+
return $this;
}
@@ -294,6 +325,7 @@ class Collection extends Iterator
}
}
$this->items = $visible;
+
return $this;
}
@@ -313,6 +345,7 @@ class Collection extends Iterator
}
}
$this->items = $modular;
+
return $this;
}
@@ -332,6 +365,7 @@ class Collection extends Iterator
}
}
$this->items = $modular;
+
return $this;
}
@@ -351,6 +385,7 @@ class Collection extends Iterator
}
}
$this->items = $published;
+
return $this;
}
@@ -370,6 +405,7 @@ class Collection extends Iterator
}
}
$this->items = $published;
+
return $this;
}
@@ -391,6 +427,7 @@ class Collection extends Iterator
}
$this->items = $routable;
+
return $this;
}
@@ -410,12 +447,15 @@ class Collection extends Iterator
}
}
$this->items = $routable;
+
return $this;
}
/**
* Creates new collection with only pages of the specified type
*
+ * @param $type
+ *
* @return Collection The collection
*/
public function ofType($type)
@@ -430,12 +470,15 @@ class Collection extends Iterator
}
$this->items = $items;
+
return $this;
}
/**
* Creates new collection with only pages of one of the specified types
*
+ * @param $types
+ *
* @return Collection The collection
*/
public function ofOneOfTheseTypes($types)
@@ -450,12 +493,15 @@ class Collection extends Iterator
}
$this->items = $items;
+
return $this;
}
/**
* Creates new collection with only pages of one of the specified access levels
*
+ * @param $accessLevels
+ *
* @return Collection The collection
*/
public function ofOneOfTheseAccessLevels($accessLevels)
@@ -472,7 +518,7 @@ class Collection extends Iterator
foreach ($page->header()->access as $index => $accessLevel) {
if (is_array($accessLevel)) {
- foreach($accessLevel as $innerIndex => $innerAccessLevel) {
+ foreach ($accessLevel as $innerIndex => $innerAccessLevel) {
if (in_array($innerAccessLevel, $accessLevels)) {
$valid = true;
}
@@ -497,11 +543,7 @@ class Collection extends Iterator
}
$this->items = $items;
+
return $this;
}
-
-
-
-
-
}
diff --git a/system/src/Grav/Common/Page/Header.php b/system/src/Grav/Common/Page/Header.php
index 4be82629d..ad59c26d3 100644
--- a/system/src/Grav/Common/Page/Header.php
+++ b/system/src/Grav/Common/Page/Header.php
@@ -5,6 +5,10 @@ namespace Grav\Common\Page;
use RocketTheme\Toolbox\ArrayTraits\Constructor;
use RocketTheme\Toolbox\ArrayTraits\NestedArrayAccess;
+/**
+ * Class Header
+ * @package Grav\Common\Page
+ */
class Header implements \ArrayAccess
{
use NestedArrayAccess, Constructor;
diff --git a/system/src/Grav/Common/Page/Media.php b/system/src/Grav/Common/Page/Media.php
index e9eeff101..dd1a38110 100644
--- a/system/src/Grav/Common/Page/Media.php
+++ b/system/src/Grav/Common/Page/Media.php
@@ -20,11 +20,11 @@ class Media extends Getters
protected $gettersVariable = 'instances';
protected $path;
- protected $instances = array();
- protected $images = array();
- protected $videos = array();
- protected $audios = array();
- protected $files = array();
+ protected $instances = [];
+ protected $images = [];
+ protected $videos = [];
+ protected $audios = [];
+ protected $files = [];
/**
* @param $path
diff --git a/system/src/Grav/Common/Page/Medium/Medium.php b/system/src/Grav/Common/Page/Medium/Medium.php
index 714eeb5e8..f1ce336fd 100644
--- a/system/src/Grav/Common/Page/Medium/Medium.php
+++ b/system/src/Grav/Common/Page/Medium/Medium.php
@@ -118,7 +118,7 @@ class Medium extends Data implements RenderableInterface
* Return PATH to file.
*
* @param bool $reset
- * @return string path to file
+ * @return string path to file
*/
public function path($reset = true)
{
diff --git a/system/src/Grav/Common/Page/Page.php b/system/src/Grav/Common/Page/Page.php
index 9b96c83b1..b9432833c 100644
--- a/system/src/Grav/Common/Page/Page.php
+++ b/system/src/Grav/Common/Page/Page.php
@@ -28,7 +28,7 @@ define('PAGE_ORDER_PREFIX_REGEX', '/^[0-9]+\./u');
* can be retrieved via public functions. Also each page can potentially contain an array of sub-pages.
* Recursively traversing the page structure allows Grav to create navigation systems.
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Page
@@ -107,8 +107,7 @@ class Page
/** @var Config $config */
$config = self::getGrav()['config'];
-
- $this->taxonomy = array();
+ $this->taxonomy = [];
$this->process = $config->get('system.pages.process');
$this->published = true;
}
@@ -127,7 +126,7 @@ class Page
$this->home_route = $config->get('system.home.alias');
$this->filePath($file->getPathName());
$this->modified($file->getMTime());
- $this->id($this->modified().md5($this->filePath()));
+ $this->id($this->modified() . md5($this->filePath()));
$this->routable(true);
$this->header();
$this->date();
@@ -139,16 +138,13 @@ class Page
$this->published();
$this->urlExtension();
-
-
// some extension logic
if (empty($extension)) {
- $this->extension('.'.$file->getExtension());
+ $this->extension('.' . $file->getExtension());
} else {
$this->extension($extension);
}
-
// extract page language from page extension
$language = trim(basename($this->extension(), 'md'), '.') ?: null;
$this->language($language);
@@ -166,13 +162,15 @@ class Page
$translatedLanguages = [];
foreach ($languages as $language) {
- $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language .'.md';
+ $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language . '.md';
if (file_exists($path)) {
$aPage = new Page();
- $aPage->init(new \SplFileInfo($path), $language .'.md');
+ $aPage->init(new \SplFileInfo($path), $language . '.md');
$route = isset($aPage->header()->routes['default']) ? $aPage->header()->routes['default'] : $aPage->rawRoute();
- if (!$route) $route = $aPage->slug();
+ if (!$route) {
+ $route = $aPage->slug();
+ }
$translatedLanguages[$language] = $route;
}
@@ -193,7 +191,7 @@ class Page
$untranslatedLanguages = [];
foreach ($languages as $language) {
- $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language .'.md';
+ $path = $this->path . DS . $this->folder . DS . $filename . '.' . $language . '.md';
if (!file_exists($path)) {
$untranslatedLanguages[] = $language;
}
@@ -206,6 +204,7 @@ class Page
* Gets and Sets the raw data
*
* @param string $var Raw content string
+ *
* @return Object Raw content string
*/
public function raw($var = null)
@@ -220,32 +219,41 @@ class Page
// Reset header and content.
$this->modified = time();
- $this->id($this->modified().md5($this->filePath()));
+ $this->id($this->modified() . md5($this->filePath()));
$this->header = null;
$this->content = null;
$this->summary = null;
}
+
return $file ? $file->raw() : '';
}
+ /**
+ * Gets and Sets the page frontmatter
+ *
+ * @param string|null $var
+ *
+ * @return string
+ */
public function frontmatter($var = null)
{
if ($var) {
- $this->frontmatter = (string) $var;
+ $this->frontmatter = (string)$var;
// Update also file object.
$file = $this->file();
if ($file) {
- $file->frontmatter((string) $var);
+ $file->frontmatter((string)$var);
}
// Force content re-processing.
- $this->id(time().md5($this->filePath()));
+ $this->id(time() . md5($this->filePath()));
}
if (!$this->frontmatter) {
$this->header();
}
+
return $this->frontmatter;
}
@@ -253,21 +261,22 @@ class Page
* Gets and Sets the header based on the YAML configuration at the top of the .md file
*
* @param object|array $var a YAML object representing the configuration for the file
+ *
* @return object the current YAML configuration
*/
public function header($var = null)
{
if ($var) {
- $this->header = (object) $var;
+ $this->header = (object)$var;
// Update also file object.
$file = $this->file();
if ($file) {
- $file->header((array) $var);
+ $file->header((array)$var);
}
// Force content re-processing.
- $this->id(time().md5($this->filePath()));
+ $this->id(time() . md5($this->filePath()));
}
if (!$this->header) {
$file = $this->file();
@@ -279,7 +288,13 @@ class Page
$this->frontmatter = $file->frontmatter();
$this->header = (object)$file->header();
} catch (ParseException $e) {
- $file->raw(self::getGrav()['language']->translate(['FRONTMATTER_ERROR_PAGE', $this->slug(), $file->filename(), $e->getMessage(), $file->raw()]));
+ $file->raw(self::getGrav()['language']->translate([
+ 'FRONTMATTER_ERROR_PAGE',
+ $this->slug(),
+ $file->filename(),
+ $e->getMessage(),
+ $file->raw()
+ ]));
$this->raw_content = $file->markdown();
$this->frontmatter = $file->frontmatter();
$this->header = (object)$file->header();
@@ -308,10 +323,10 @@ class Page
$this->menu = trim($this->header->menu);
}
if (isset($this->header->routable)) {
- $this->routable = (bool) $this->header->routable;
+ $this->routable = (bool)$this->header->routable;
}
if (isset($this->header->visible)) {
- $this->visible = (bool) $this->header->visible;
+ $this->visible = (bool)$this->header->visible;
}
if (isset($this->header->redirect)) {
$this->redirect = trim($this->header->redirect);
@@ -332,7 +347,7 @@ class Page
$this->markdown_extra = (bool)$this->header->markdown_extra;
}
if (isset($this->header->taxonomy)) {
- foreach ((array) $this->header->taxonomy as $taxonomy => $taxitems) {
+ foreach ((array)$this->header->taxonomy as $taxonomy => $taxitems) {
$this->taxonomy[$taxonomy] = (array)$taxitems;
}
}
@@ -340,12 +355,12 @@ class Page
$this->max_count = intval($this->header->max_count);
}
if (isset($this->header->process)) {
- foreach ((array) $this->header->process as $process => $status) {
- $this->process[$process] = (bool) $status;
+ foreach ((array)$this->header->process as $process => $status) {
+ $this->process[$process] = (bool)$status;
}
}
if (isset($this->header->published)) {
- $this->published = (bool) $this->header->published;
+ $this->published = (bool)$this->header->published;
}
if (isset($this->header->publish_date)) {
$this->publishDate($this->header->publish_date);
@@ -357,10 +372,10 @@ class Page
$this->expires = intval($this->header->expires);
}
if (isset($this->header->etag)) {
- $this->etag = (bool) $this->header->etag;
+ $this->etag = (bool)$this->header->etag;
}
if (isset($this->header->last_modified)) {
- $this->last_modified = (bool) $this->header->last_modified;
+ $this->last_modified = (bool)$this->header->last_modified;
}
if (isset($this->header->ssl)) {
$this->ssl = (bool) $this->header->ssl;
@@ -400,12 +415,13 @@ class Page
/**
* Get the summary.
*
- * @param int $size Max summary size.
+ * @param int $size Max summary size.
+ *
* @return string
*/
public function summary($size = null)
{
- $config = (array) self::getGrav()['config']->get('site.summary');
+ $config = (array)self::getGrav()['config']->get('site.summary');
if (isset($this->header->summary)) {
$config = array_merge($config, $this->header->summary);
}
@@ -427,7 +443,7 @@ class Page
// Return calculated summary based on summary divider's position
$format = $config['format'];
// Return entire page content on wrong/ unknown format
- if (!in_array($format, array('short', 'long'))) {
+ if (!in_array($format, ['short', 'long'])) {
return $content;
} elseif (($format === 'short') && isset($summary_size)) {
return mb_substr($content, 0, $summary_size);
@@ -441,7 +457,7 @@ class Page
// If the size is zero, return the entire page content
if ($size === 0) {
return $content;
- // Return calculated summary based on defaults
+ // Return calculated summary based on defaults
} elseif (!is_numeric($size) || ($size < 0)) {
$size = 300;
}
@@ -452,7 +468,7 @@ class Page
/**
* Sets the summary of the page
*
- * @param string $var Summary
+ * @param string $summary Summary
*/
public function setSummary($summary)
{
@@ -463,6 +479,7 @@ class Page
* Gets and Sets the content based on content portion of the .md file
*
* @param string $var Content
+ *
* @return string Content
*/
public function content($var = null)
@@ -477,7 +494,7 @@ class Page
}
// Force re-processing.
- $this->id(time().md5($this->filePath()));
+ $this->id(time() . md5($this->filePath()));
$this->content = null;
}
// If no content, process it
@@ -491,13 +508,15 @@ class Page
// Load cached content
/** @var Cache $cache */
$cache = self::getGrav()['cache'];
- $cache_id = md5('page'.$this->id());
+ $cache_id = md5('page' . $this->id());
$this->content = $cache->fetch($cache_id);
$process_markdown = $this->shouldProcess('markdown');
$process_twig = $this->shouldProcess('twig');
- $cache_enable = isset($this->header->cache_enable) ? $this->header->cache_enable : $config->get('system.cache.enabled', true);
- $twig_first = isset($this->header->twig_first) ? $this->header->twig_first : $config->get('system.pages.twig_first', true);
+ $cache_enable = isset($this->header->cache_enable) ? $this->header->cache_enable : $config->get('system.cache.enabled',
+ true);
+ $twig_first = isset($this->header->twig_first) ? $this->header->twig_first : $config->get('system.pages.twig_first',
+ true);
// if no cached-content run everything
@@ -555,7 +574,7 @@ class Page
/** @var Config $config */
$config = self::getGrav()['config'];
- $defaults = (array) $config->get('system.pages.markdown');
+ $defaults = (array)$config->get('system.pages.markdown');
if (isset($this->header()->markdown)) {
$defaults = array_merge($defaults, $this->header()->markdown);
}
@@ -591,7 +610,7 @@ class Page
private function cachePageContent()
{
$cache = self::getGrav()['cache'];
- $cache_id = md5('page'.$this->id());
+ $cache_id = md5('page' . $this->id());
$cache->save($cache_id, $this->content);
}
@@ -618,8 +637,9 @@ class Page
/**
* Get value from a page variable (used mostly for creating edit forms).
*
- * @param string $name Variable name.
- * @param mixed $default
+ * @param string $name Variable name.
+ * @param mixed $default
+ *
* @return mixed
*/
public function value($name, $default = null)
@@ -632,21 +652,24 @@ class Page
}
if ($name == 'order') {
$order = $this->order();
- return $order ? (int) $this->order() : '';
+
+ return $order ? (int)$this->order() : '';
}
if ($name == 'ordering') {
- return (bool) $this->order();
+ return (bool)$this->order();
}
if ($name == 'folder') {
$regex = '/^[0-9]+\./u';
+
return preg_replace($regex, '', $this->folder);
}
if ($name == 'name') {
$language = $this->language() ? '.' . $this->language() : '';
- $name_val = str_replace($language .'.md', '', $this->name());
+ $name_val = str_replace($language . '.md', '', $this->name());
if ($this->modular()) {
return 'modular/' . $name_val;
}
+
return $name_val;
}
if ($name == 'media') {
@@ -690,6 +713,13 @@ class Page
return $default;
}
+ /**
+ * Gets and Sets the Page raw content
+ *
+ * @param null $var
+ *
+ * @return null
+ */
public function rawMarkdown($var = null)
{
if ($var !== null) {
@@ -709,11 +739,13 @@ class Page
if ($this->name) {
return MarkdownFile::instance($this->filePath());
}
+
return null;
}
/**
* Save page if there's a file assigned to it.
+ *
* @param bool $reorder Internal use.
*/
public function save($reorder = true)
@@ -724,7 +756,7 @@ class Page
$file = $this->file();
if ($file) {
$file->filename($this->filePath());
- $file->header((array) $this->header());
+ $file->header((array)$this->header());
$file->markdown($this->raw_content);
$file->save();
}
@@ -736,6 +768,7 @@ class Page
* You need to call $this->save() in order to perform the move.
*
* @param Page $parent New parent page.
+ *
* @return $this
*/
public function move(Page $parent)
@@ -747,16 +780,16 @@ class Page
$this->_action = 'move';
$this->parent($parent);
- $this->id(time().md5($this->filePath()));
+ $this->id(time() . md5($this->filePath()));
if ($parent->path()) {
$this->path($parent->path() . '/' . $this->folder());
}
if ($parent->route()) {
- $this->route($parent->route() . '/'. $this->slug());
+ $this->route($parent->route() . '/' . $this->slug());
} else {
- $this->route(self::getGrav()['pages']->root()->route() . '/'. $this->slug());
+ $this->route(self::getGrav()['pages']->root()->route() . '/' . $this->slug());
}
return $this;
@@ -769,6 +802,7 @@ class Page
* You need to call $this->save() in order to perform the move.
*
* @param Page $parent New parent page.
+ *
* @return $this
*/
public function copy($parent)
@@ -849,6 +883,7 @@ class Page
public function extra()
{
$blueprints = $this->blueprints();
+
return $blueprints->extra($this->toArray()['header'], 'header.');
}
@@ -859,10 +894,10 @@ class Page
*/
public function toArray()
{
- return array(
- 'header' => (array) $this->header(),
- 'content' => (string) $this->value('content')
- );
+ return [
+ 'header' => (array)$this->header(),
+ 'content' => (string)$this->value('content')
+ ];
}
/**
@@ -889,6 +924,7 @@ class Page
* Gets and sets the associated media as found in the page folder.
*
* @param Media $var Representation of associated media.
+ *
* @return Media Representation of associated media.
*/
public function media($var = null)
@@ -901,13 +937,14 @@ class Page
}
if ($this->media === null) {
// Use cached media if possible.
- $media_cache_id = md5('media'.$this->id());
+ $media_cache_id = md5('media' . $this->id());
if (!$media = $cache->fetch($media_cache_id)) {
$media = new Media($this->path());
$cache->save($media_cache_id, $media);
}
$this->media = $media;
}
+
return $this->media;
}
@@ -915,6 +952,7 @@ class Page
* Gets and sets the name field. If no name field is set, it will return 'default.md'.
*
* @param string $var The name of this page.
+ *
* @return string The name of this page.
*/
public function name($var = null)
@@ -922,6 +960,7 @@ class Page
if ($var !== null) {
$this->name = $var;
}
+
return empty($this->name) ? 'default.md' : $this->name;
}
@@ -932,7 +971,7 @@ class Page
*/
public function childType()
{
- return isset($this->header->child_type) ? (string) $this->header->child_type : 'default';
+ return isset($this->header->child_type) ? (string)$this->header->child_type : 'default';
}
/**
@@ -940,6 +979,7 @@ class Page
* If no field is set, it will return the name without the .md extension
*
* @param string $var the template name
+ *
* @return string the template name
*/
public function template($var = null)
@@ -950,6 +990,7 @@ class Page
if (empty($this->template)) {
$this->template = ($this->modular() ? 'modular/' : '') . str_replace($this->extension(), '', $this->name());
}
+
return $this->template;
}
@@ -957,6 +998,7 @@ class Page
* Gets and sets the extension field.
*
* @param null $var
+ *
* @return null|string
*/
public function extension($var = null)
@@ -967,31 +1009,43 @@ class Page
if (empty($this->extension)) {
$this->extension = '.' . pathinfo($this->name(), PATHINFO_EXTENSION);
}
+
return $this->extension;
}
+ /**
+ * Returns the page extension, got from the page `url_extension` config and falls back to the
+ * system config `system.pages.append_url_extension`.
+ *
+ * @return string The extension of this page. For example `.html`
+ */
public function urlExtension()
{
+ if ($this->home()) {
+ return '';
+ }
+
// if not set in the page get the value from system config
if (empty($this->url_extension)) {
$this->url_extension = trim(isset($this->header->append_url_extension) ? $this->header->append_url_extension : self::getGrav()['config']->get('system.pages.append_url_extension', false));
}
return $this->url_extension;
-
}
/**
* Gets and sets the expires field. If not set will return the default
*
- * @param string $var The name of this page.
- * @return string The name of this page.
+ * @param int $var The new expires value.
+ *
+ * @return int The expires value
*/
public function expires($var = null)
{
if ($var !== null) {
$this->expires = $var;
}
+
return empty($this->expires) ? self::getGrav()['config']->get('system.pages.expires') : $this->expires;
}
@@ -999,6 +1053,7 @@ class Page
* Gets and sets the title for this Page. If no title is set, it will use the slug() to get a name
*
* @param string $var the title of the Page
+ *
* @return string the title of the Page
*/
public function title($var = null)
@@ -1009,6 +1064,7 @@ class Page
if (empty($this->title)) {
$this->title = ucfirst($this->slug());
}
+
return $this->title;
}
@@ -1017,6 +1073,7 @@ class Page
* If no menu field is set, it will use the title()
*
* @param string $var the menu field for the page
+ *
* @return string the menu field for the page
*/
public function menu($var = null)
@@ -1027,6 +1084,7 @@ class Page
if (empty($this->menu)) {
$this->menu = $this->title();
}
+
return $this->menu;
}
@@ -1034,12 +1092,13 @@ class Page
* Gets and Sets whether or not this Page is visible for navigation
*
* @param bool $var true if the page is visible
+ *
* @return bool true if the page is visible
*/
public function visible($var = null)
{
if ($var !== null) {
- $this->visible = (bool) $var;
+ $this->visible = (bool)$var;
}
if ($this->visible === null) {
@@ -1052,6 +1111,7 @@ class Page
$this->visible = false;
}
}
+
return $this->visible;
}
@@ -1059,12 +1119,13 @@ class Page
* Gets and Sets whether or not this Page is considered published
*
* @param bool $var true if the page is published
+ *
* @return bool true if the page is published
*/
public function published($var = null)
{
if ($var !== null) {
- $this->published = (bool) $var;
+ $this->published = (bool)$var;
}
// If not published, should not be visible in menus either
@@ -1079,6 +1140,7 @@ class Page
* Gets and Sets the Page publish date
*
* @param string $var string representation of a date
+ *
* @return int unix timestamp representation of the date
*/
public function publishDate($var = null)
@@ -1094,6 +1156,7 @@ class Page
* Gets and Sets the Page unpublish date
*
* @param string $var string representation of a date
+ *
* @return int|null unix timestamp representation of the date
*/
public function unpublishDate($var = null)
@@ -1111,12 +1174,13 @@ class Page
* The page must be *routable* and *published*
*
* @param bool $var true if the page is routable
+ *
* @return bool true if the page is routable
*/
public function routable($var = null)
{
if ($var !== null) {
- $this->routable = (bool) $var;
+ $this->routable = (bool)$var;
}
return $this->routable && $this->published();
@@ -1136,13 +1200,15 @@ class Page
* a simple array of arrays with the form array("markdown"=>true) for example
*
* @param array $var an Array of name value pairs where the name is the process and value is true or false
+ *
* @return array an Array of name value pairs where the name is the process and value is true or false
*/
public function process($var = null)
{
if ($var !== null) {
- $this->process = (array) $var;
+ $this->process = (array)$var;
}
+
return $this->process;
}
@@ -1151,12 +1217,13 @@ class Page
* that can then be rendered in the page.
*
* @param array $var an Array of metadata values to set
+ *
* @return array an Array of metadata values for the page
*/
public function metadata($var = null)
{
if ($var !== null) {
- $this->metadata = (array) $var;
+ $this->metadata = (array)$var;
}
// if not metadata yet, process it.
@@ -1170,7 +1237,7 @@ class Page
$metadata['generator'] = 'GravCMS';
// Get initial metadata for the page
- $metadata = array_merge($metadata, self::getGrav()['config']->get('site.metadata'));
+ $metadata = array_merge($metadata, self::getGrav()['config']->get('site.metadata'));
if (isset($this->header->metadata)) {
// Merge any site.metadata settings in with page metadata
@@ -1182,16 +1249,22 @@ class Page
// If this is a property type metadata: "og", "twitter", "facebook" etc
if (is_array($value)) {
foreach ($value as $property => $prop_value) {
- $prop_key = $key.":".$property;
- $this->metadata[$prop_key] = array('property'=>$prop_key, 'content'=>htmlspecialchars($prop_value, ENT_QUOTES));
+ $prop_key = $key . ":" . $property;
+ $this->metadata[$prop_key] = [
+ 'property' => $prop_key,
+ 'content' => htmlspecialchars($prop_value, ENT_QUOTES)
+ ];
}
- // If it this is a standard meta data type
+ // If it this is a standard meta data type
} else {
if ($value) {
if (in_array($key, $header_tag_http_equivs)) {
- $this->metadata[$key] = array('http_equiv'=>$key, 'content'=>htmlspecialchars($value, ENT_QUOTES));
+ $this->metadata[$key] = [
+ 'http_equiv' => $key,
+ 'content' => htmlspecialchars($value, ENT_QUOTES)
+ ];
} else {
- $this->metadata[$key] = array('name'=>$key, 'content'=>htmlspecialchars($value, ENT_QUOTES));
+ $this->metadata[$key] = ['name' => $key, 'content' => htmlspecialchars($value, ENT_QUOTES)];
}
}
}
@@ -1207,6 +1280,7 @@ class Page
* the parent folder from the path
*
* @param string $var the slug, e.g. 'my-blog'
+ *
* @return string the slug
*/
public function slug($var = null)
@@ -1226,6 +1300,7 @@ class Page
* Get/set order number of this page.
*
* @param int $var
+ *
* @return int|bool
*/
public function order($var = null)
@@ -1252,6 +1327,7 @@ class Page
* Gets the URL for a page - alias of url().
*
* @param bool $include_host
+ *
* @return string the permalink
*/
public function link($include_host = false)
@@ -1262,14 +1338,14 @@ class Page
/**
* Gets the url for the Page.
*
- * @param bool $include_host Defaults false, but true would include http://yourhost.com
- * @param bool $canonical true to return the canonical URL
+ * @param bool $include_host Defaults false, but true would include http://yourhost.com
+ * @param bool $canonical true to return the canonical URL
+ * @param bool $include_lang
*
* @return string The url.
*/
public function url($include_host = false, $canonical = false, $include_lang = true)
{
-
/** @var Pages $pages */
$pages = self::getGrav()['pages'];
@@ -1286,7 +1362,7 @@ class Page
// get pre-route
if ($include_lang && $language->enabled()) {
- $pre_route = $language->getLanguageURLPrefix();
+ $pre_route = $language->getLanguageURLPrefix();
} else {
$pre_route = '';
}
@@ -1305,7 +1381,7 @@ class Page
$rootUrl = $uri->rootUrl($include_host) . $pages->base();
- $url = $rootUrl.'/'.trim($route, '/') . $this->urlExtension();
+ $url = $rootUrl . '/' . trim($route, '/') . $this->urlExtension();
// trim trailing / if not root
if ($url !== '/') {
@@ -1319,7 +1395,7 @@ class Page
* Gets the route for the page based on the route headers if available, else from
* the parents route and the current Page's slug.
*
- * @param string $var Set new default route.
+ * @param string $var Set new default route.
*
* @return string The route for the Page.
*/
@@ -1338,15 +1414,16 @@ class Page
if ($this->hide_home_route && $parent->route() == $this->home_route) {
$baseRoute = '';
} else {
- $baseRoute = (string) $parent->route();
+ $baseRoute = (string)$parent->route();
}
}
- $this->route = isset($baseRoute) ? $baseRoute . '/'. $this->slug() : null;
+ $this->route = isset($baseRoute) ? $baseRoute . '/' . $this->slug() : null;
if (!empty($this->routes) && isset($this->routes['default'])) {
$this->routes['aliases'][] = $this->route;
$this->route = $this->routes['default'];
+
return $this->route;
}
}
@@ -1363,6 +1440,13 @@ class Page
unset($this->slug);
}
+ /**
+ * Gets and Sets the page raw route
+ *
+ * @param null $var
+ *
+ * @return null|string
+ */
public function rawRoute($var = null)
{
if ($var !== null) {
@@ -1370,12 +1454,12 @@ class Page
}
if (empty($this->raw_route)) {
- $baseRoute = $this->parent ? (string) $this->parent()->rawRoute() : null;
+ $baseRoute = $this->parent ? (string)$this->parent()->rawRoute() : null;
$regex = '/^[0-9]+\./u';
$slug = preg_replace($regex, '', $this->folder);
- $this->raw_route = isset($baseRoute) ? $baseRoute . '/'. $slug : null;
+ $this->raw_route = isset($baseRoute) ? $baseRoute . '/' . $slug : null;
}
return $this->raw_route;
@@ -1384,14 +1468,14 @@ class Page
/**
* Gets the route aliases for the page based on page headers.
*
- * @param array $var list of route aliases
+ * @param array $var list of route aliases
*
* @return array The route aliases for the Page.
*/
public function routeAliases($var = null)
{
if ($var !== null) {
- $this->routes['aliases'] = (array) $var;
+ $this->routes['aliases'] = (array)$var;
}
if (!empty($this->routes) && isset($this->routes['aliases'])) {
@@ -1426,6 +1510,7 @@ class Page
* Gets and sets the identifier for this Page object.
*
* @param string $var the identifier
+ *
* @return string the identifier
*/
public function id($var = null)
@@ -1433,6 +1518,7 @@ class Page
if ($var !== null) {
$this->id = $var;
}
+
return $this->id;
}
@@ -1440,6 +1526,7 @@ class Page
* Gets and sets the modified timestamp.
*
* @param int $var modified unix timestamp
+ *
* @return int modified unix timestamp
*/
public function modified($var = null)
@@ -1455,6 +1542,7 @@ class Page
* Gets the redirect set in the header.
*
* @param string $var redirect url
+ *
* @return array
*/
public function redirect($var = null)
@@ -1462,6 +1550,7 @@ class Page
if ($var !== null) {
$this->redirect = $var;
}
+
return $this->redirect;
}
@@ -1469,6 +1558,7 @@ class Page
* Gets and sets the option to show the etag header for the page.
*
* @param boolean $var show etag header
+ *
* @return boolean show etag header
*/
public function eTag($var = null)
@@ -1477,8 +1567,9 @@ class Page
$this->etag = $var;
}
if (!isset($this->etag)) {
- $this->etag = (bool) self::getGrav()['config']->get('system.pages.etag');
+ $this->etag = (bool)self::getGrav()['config']->get('system.pages.etag');
}
+
return $this->etag;
}
@@ -1486,6 +1577,7 @@ class Page
* Gets and sets the option to show the last_modified header for the page.
*
* @param boolean $var show last_modified header
+ *
* @return boolean show last_modified header
*/
public function lastModified($var = null)
@@ -1494,8 +1586,9 @@ class Page
$this->last_modified = $var;
}
if (!isset($this->last_modified)) {
- $this->last_modified = (bool) self::getGrav()['config']->get('system.pages.last_modified');
+ $this->last_modified = (bool)self::getGrav()['config']->get('system.pages.last_modified');
}
+
return $this->last_modified;
}
@@ -1503,6 +1596,7 @@ class Page
* Gets and sets the path to the .md file for this Page object.
*
* @param string $var the file path
+ *
* @return string|null the file path
*/
public function filePath($var = null)
@@ -1515,6 +1609,7 @@ class Page
// Path to the page.
$this->path = dirname(dirname($var));
}
+
return $this->path . '/' . $this->folder . '/' . ($this->name ?: '');
}
@@ -1526,6 +1621,7 @@ class Page
public function filePathClean()
{
$path = str_replace(ROOT_DIR, '', $this->filePath());
+
return $path;
}
@@ -1534,7 +1630,8 @@ class Page
*/
public function relativePagePath()
{
- $path = str_replace('/'.$this->name, '', $this->filePathClean());
+ $path = str_replace('/' . $this->name, '', $this->filePathClean());
+
return $path;
}
@@ -1543,6 +1640,7 @@ class Page
* This is equivalent to the filePath but without the filename.
*
* @param string $var the path
+ *
* @return string|null the path
*/
public function path($var = null)
@@ -1553,6 +1651,7 @@ class Page
// Path to the page.
$this->path = dirname($var);
}
+
return $this->path ? $this->path . '/' . $this->folder : null;
}
@@ -1560,6 +1659,7 @@ class Page
* Get/set the folder.
*
* @param string $var Optional path
+ *
* @return string|null
*/
public function folder($var = null)
@@ -1567,6 +1667,7 @@ class Page
if ($var !== null) {
$this->folder = $var;
}
+
return $this->folder;
}
@@ -1574,6 +1675,7 @@ class Page
* Gets and sets the date for this Page object. This is typically passed in via the page headers
*
* @param string $var string representation of a date
+ *
* @return int unix timestamp representation of the date
*/
public function date($var = null)
@@ -1591,7 +1693,9 @@ class Page
/**
* Gets and sets the order by which any sub-pages should be sorted.
+ *
* @param string $var the order, either "asc" or "desc"
+ *
* @return string the order, either "asc" or "desc"
*/
public function orderDir($var = null)
@@ -1602,6 +1706,7 @@ class Page
if (empty($this->order_dir)) {
$this->order_dir = 'asc';
}
+
return $this->order_dir;
}
@@ -1614,6 +1719,7 @@ class Page
* folder - is the order based on the name of the folder with any numerics omitted
*
* @param string $var supported options include "default", "title", "date", and "folder"
+ *
* @return string supported options include "default", "title", "date", and "folder"
*/
public function orderBy($var = null)
@@ -1621,6 +1727,7 @@ class Page
if ($var !== null) {
$this->order_by = $var;
}
+
return $this->order_by;
}
@@ -1628,6 +1735,7 @@ class Page
* Gets the manual order set in the header.
*
* @param string $var supported options include "default", "title", "date", and "folder"
+ *
* @return array
*/
public function orderManual($var = null)
@@ -1635,7 +1743,8 @@ class Page
if ($var !== null) {
$this->order_manual = $var;
}
- return (array) $this->order_manual;
+
+ return (array)$this->order_manual;
}
/**
@@ -1643,18 +1752,20 @@ class Page
* sub_pages header property is set for this page object.
*
* @param int $var the maximum number of sub-pages
+ *
* @return int the maximum number of sub-pages
*/
public function maxCount($var = null)
{
if ($var !== null) {
- $this->max_count = (int) $var;
+ $this->max_count = (int)$var;
}
if (empty($this->max_count)) {
/** @var Config $config */
$config = self::getGrav()['config'];
- $this->max_count = (int) $config->get('system.pages.list.count');
+ $this->max_count = (int)$config->get('system.pages.list.count');
}
+
return $this->max_count;
}
@@ -1662,6 +1773,7 @@ class Page
* Gets and sets the taxonomy array which defines which taxonomies this page identifies itself with.
*
* @param array $var an array of taxonomies
+ *
* @return array an array of taxonomies
*/
public function taxonomy($var = null)
@@ -1669,13 +1781,15 @@ class Page
if ($var !== null) {
$this->taxonomy = $var;
}
+
return $this->taxonomy;
}
- /**
+ /**
* Gets and sets the modular var that helps identify this parent page contains modular pages.
*
* @param bool $var true if modular_twig
+ *
* @return bool true if modular_twig
*/
public function modular($var = null)
@@ -1688,12 +1802,13 @@ class Page
* twig processing handled differently from a regular page.
*
* @param bool $var true if modular_twig
+ *
* @return bool true if modular_twig
*/
public function modularTwig($var = null)
{
if ($var !== null) {
- $this->modular_twig = (bool) $var;
+ $this->modular_twig = (bool)$var;
if ($var) {
$this->process['twig'] = true;
$this->visible(false);
@@ -1703,6 +1818,7 @@ class Page
}
}
}
+
return $this->modular_twig;
}
@@ -1710,23 +1826,26 @@ class Page
* Gets the configured state of the processing method.
*
* @param string $process the process, eg "twig" or "markdown"
+ *
* @return bool whether or not the processing method is enabled for this Page
*/
public function shouldProcess($process)
{
- return isset($this->process[$process]) ? (bool) $this->process[$process] : false;
+ return isset($this->process[$process]) ? (bool)$this->process[$process] : false;
}
/**
* Gets and Sets the parent object for this page
*
* @param Page $var the parent page object
+ *
* @return Page|null the parent page object if it exists.
*/
public function parent(Page $var = null)
{
if ($var) {
$this->parent = $var->path();
+
return $var;
}
@@ -1770,6 +1889,7 @@ class Page
{
/** @var Pages $pages */
$pages = self::getGrav()['pages'];
+
return $pages->children($this->path());
}
@@ -1785,6 +1905,7 @@ class Page
if ($collection instanceof Collection) {
return $collection->isFirst($this->path());
}
+
return true;
}
@@ -1799,6 +1920,7 @@ class Page
if ($collection instanceof Collection) {
return $collection->isLast($this->path());
}
+
return true;
}
@@ -1826,6 +1948,7 @@ class Page
* Returns the adjacent sibling based on a direction.
*
* @param integer $direction either -1 or +1
+ *
* @return Page the sibling page
*/
public function adjacentSibling($direction = 1)
@@ -1834,6 +1957,7 @@ class Page
if ($collection instanceof Collection) {
return $collection->adjacentSibling($this->path(), $direction);
}
+
return false;
}
@@ -1853,6 +1977,7 @@ class Page
}
}
+
return false;
}
@@ -1870,6 +1995,7 @@ class Page
$routes = self::getGrav()['pages']->routes();
if (isset($routes[$uri_path])) {
+ /** @var Page $child_page */
$child_page = $pages->dispatch($uri->route())->parent();
if ($child_page) {
while (!$child_page->root()) {
@@ -1911,8 +2037,8 @@ class Page
/**
* Helper method to return a page.
*
- * @param string $url the url of the page
- * @param bool $all
+ * @param string $url the url of the page
+ * @param bool $all
*
* @return \Grav\Common\Page\Page page you were looking for if it exists
*/
@@ -1920,6 +2046,7 @@ class Page
{
/** @var Pages $pages */
$pages = self::getGrav()['pages'];
+
return $pages->dispatch($url, $all);
}
@@ -1927,20 +2054,21 @@ class Page
* Get a collection of pages in the current context.
*
* @param string|array $params
- * @param boolean $pagination
+ * @param boolean $pagination
+ *
* @return Collection
* @throws \InvalidArgumentException
*/
public function collection($params = 'content', $pagination = true)
{
if (is_string($params)) {
- $params = (array) $this->value('header.'.$params);
+ $params = (array)$this->value('header.' . $params);
} elseif (!is_array($params)) {
throw new \InvalidArgumentException('Argument should be either header variable name or array of parameters');
}
if (!isset($params['items'])) {
- return array();
+ return [];
}
$collection = $this->evaluate($params['items']);
@@ -1957,7 +2085,7 @@ class Page
$process_taxonomy = isset($params['url_taxonomy_filters']) ? $params['url_taxonomy_filters'] : $config->get('system.pages.url_taxonomy_filters');
if ($process_taxonomy) {
- foreach ((array) $config->get('site.taxonomies') as $taxonomy) {
+ foreach ((array)$config->get('site.taxonomies') as $taxonomy) {
if ($uri->param($taxonomy)) {
$items = explode(',', $uri->param($taxonomy));
$collection->setParams(['taxonomies' => [$taxonomy => $items]]);
@@ -1968,8 +2096,9 @@ class Page
continue;
}
foreach ($items as $item) {
- if (empty($page->taxonomy[$taxonomy])
- || !in_array(htmlspecialchars_decode($item, ENT_QUOTES), $page->taxonomy[$taxonomy])) {
+ if (empty($page->taxonomy[$taxonomy]) || !in_array(htmlspecialchars_decode($item,
+ ENT_QUOTES), $page->taxonomy[$taxonomy])
+ ) {
$collection->remove();
}
}
@@ -2025,21 +2154,22 @@ class Page
if (is_string($value)) {
// Format: @command.param
$cmd = $value;
- $params = array();
+ $params = [];
} elseif (is_array($value) && count($value) == 1 && !is_int(key($value))) {
// Format: @command.param: { attr1: value1, attr2: value2 }
- $cmd = (string) key($value);
- $params = (array) current($value);
+ $cmd = (string)key($value);
+ $params = (array)current($value);
} else {
$result = [];
- foreach($value as $key => $val) {
+ foreach ($value as $key => $val) {
if (is_int($key)) {
$result = $result + $this->evaluate($val)->toArray();
} else {
- $result = $result + $this->evaluate([$key=>$val])->toArray();
+ $result = $result + $this->evaluate([$key => $val])->toArray();
}
}
+
return new Collection($result);
}
@@ -2054,7 +2184,9 @@ class Page
$parts = explode('.', $cmd);
$current = array_shift($parts);
+ /** @var Collection $results */
$results = new Collection();
+
switch ($current) {
case '@self':
if (!empty($parts)) {
@@ -2163,6 +2295,7 @@ class Page
if ($this->name) {
return true;
}
+
return false;
}
@@ -2184,6 +2317,7 @@ class Page
public function exists()
{
$file = $this->file();
+
return $file && $file->exists();
}
@@ -2191,6 +2325,7 @@ class Page
* Cleans the path.
*
* @param string $path the path
+ *
* @return string the path
*/
protected function cleanPath($path)
@@ -2199,6 +2334,7 @@ class Page
if (strpos($lastchunk, ':') !== false) {
$path = str_replace($lastchunk, '', $path);
}
+
return $path;
}
@@ -2206,6 +2342,10 @@ class Page
* Moves or copies the page in filesystem.
*
* @internal
+ *
+ * @param bool $reorder
+ *
+ * @throws Exception
*/
protected function doRelocation($reorder)
{
@@ -2221,7 +2361,7 @@ class Page
$parent = $this->parent();
// Extract visible children from the parent page.
- $list = array();
+ $list = [];
/** @var Page $page */
foreach ($parent->children()->visible() as $page) {
if ($page->order()) {
@@ -2238,21 +2378,21 @@ class Page
// Then add it back to the new location (if needed).
if ($this->order()) {
- array_splice($list, min($this->order()-1, count($list)), 0, array($this->path()));
+ array_splice($list, min($this->order() - 1, count($list)), 0, [$this->path()]);
}
// Reorder all moved pages.
foreach ($list as $order => $path) {
if ($path == $this->path()) {
// Handle current page; we do want to change ordering number, but nothing else.
- $this->order($order+1);
+ $this->order($order + 1);
} else {
// Handle all the other pages.
$page = $pages->get($path);
- if ($page && $page->exists() && !$page->_action && $page->order() != $order+1) {
+ if ($page && $page->exists() && !$page->_action && $page->order() != $order + 1) {
$page = $page->move($parent);
- $page->order($order+1);
+ $page->order($order + 1);
$page->save(false);
}
}
diff --git a/system/src/Grav/Common/Page/Pages.php b/system/src/Grav/Common/Page/Pages.php
index 2dd1bbadf..df5259899 100644
--- a/system/src/Grav/Common/Page/Pages.php
+++ b/system/src/Grav/Common/Page/Pages.php
@@ -1,15 +1,15 @@
$this->last_modified) {
$this->last_modified = $modified;
}
+
return $this->last_modified;
}
@@ -151,8 +154,8 @@ class Pages
/**
* Adds a page and assigns a route to it.
*
- * @param Page $page Page to be added.
- * @param string $route Optional route (uses route from the object if not set).
+ * @param Page $page Page to be added.
+ * @param string $route Optional route (uses route from the object if not set).
*/
public function addPage(Page $page, $route = null)
{
@@ -161,7 +164,7 @@ class Pages
}
$route = $page->route($route);
if ($page->parent()) {
- $this->children[$page->parent()->path()][$page->path()] = array('slug' => $page->slug());
+ $this->children[$page->parent()->path()][$page->path()] = ['slug' => $page->slug()];
}
$this->routes[$route] = $page->path();
}
@@ -169,7 +172,7 @@ class Pages
/**
* Sort sub-pages in a page.
*
- * @param Page $page
+ * @param Page $page
* @param string $order_by
* @param string $order_dir
*
@@ -185,7 +188,7 @@ class Pages
}
$path = $page->path();
- $children = isset($this->children[$path]) ? $this->children[$path] : array();
+ $children = isset($this->children[$path]) ? $this->children[$path] : [];
if (!$children) {
return $children;
@@ -206,9 +209,10 @@ class Pages
/**
* @param Collection $collection
- * @param $orderBy
- * @param string $orderDir
- * @param null $orderManual
+ * @param $orderBy
+ * @param string $orderDir
+ * @param null $orderManual
+ *
* @return array
* @internal
*/
@@ -219,7 +223,7 @@ class Pages
return [];
}
- $lookup = md5(json_encode($items));
+ $lookup = md5(json_encode($items) . json_encode($orderManual) . $orderBy . $orderDir);
if (!isset($this->sort[$lookup][$orderBy])) {
$this->buildSort($lookup, $items, $orderBy, $orderManual);
}
@@ -237,7 +241,8 @@ class Pages
/**
* Get a page instance.
*
- * @param string $path The filesystem full path of the page
+ * @param string $path The filesystem full path of the page
+ *
* @return Page
* @throws \Exception
*/
@@ -246,26 +251,30 @@ class Pages
if (!is_null($path) && !is_string($path)) {
throw new \Exception();
}
- return isset($this->instances[(string) $path]) ? $this->instances[(string) $path] : null;
+
+ return isset($this->instances[(string)$path]) ? $this->instances[(string)$path] : null;
}
/**
* Get children of the path.
*
* @param string $path
+ *
* @return Collection
*/
public function children($path)
{
- $children = isset($this->children[(string) $path]) ? $this->children[(string) $path] : array();
- return new Collection($children, array(), $this);
+ $children = isset($this->children[(string)$path]) ? $this->children[(string)$path] : [];
+
+ return new Collection($children, [], $this);
}
/**
* Dispatch URI to a page.
*
* @param string $url The relative URL of the page
- * @param bool $all
+ * @param bool $all
+ *
* @return Page|null
*/
public function dispatch($url, $all = false)
@@ -297,28 +306,34 @@ class Pages
$page = $this->dispatch($route, $all);
} else {
// Try Regex style redirects
- foreach ((array)$config->get("site.redirects") as $pattern => $replace) {
- $pattern = '#' . $pattern . '#';
- try {
- $found = preg_replace($pattern, $replace, $url);
- if ($found != $url) {
- $this->grav->redirectLangSafe($found);
+ $site_redirects = $config->get("site.redirects");
+ if (is_array($site_redirects)) {
+ foreach ((array)$site_redirects as $pattern => $replace) {
+ $pattern = '#' . $pattern . '#';
+ try {
+ $found = preg_replace($pattern, $replace, $url);
+ if ($found != $url) {
+ $this->grav->redirectLangSafe($found);
+ }
+ } catch (ErrorException $e) {
+ $this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage());
}
- } catch (ErrorException $e) {
- $this->grav['log']->error('site.redirects: ' . $pattern . '-> ' . $e->getMessage());
}
}
// Try Regex style routes
- foreach ((array)$config->get("site.routes") as $pattern => $replace) {
- $pattern = '#' . $pattern . '#';
- try {
- $found = preg_replace($pattern, $replace, $url);
- if ($found != $url) {
- $page = $this->dispatch($found, $all);
+ $site_routes = $config->get("site.routes");
+ if (is_array($site_routes)) {
+ foreach ((array)$site_routes as $pattern => $replace) {
+ $pattern = '#' . $pattern . '#';
+ try {
+ $found = preg_replace($pattern, $replace, $url);
+ if ($found != $url) {
+ $page = $this->dispatch($found, $all);
+ }
+ } catch (ErrorException $e) {
+ $this->grav['log']->error('site.routes: ' . $pattern . '-> ' . $e->getMessage());
}
- } catch (ErrorException $e) {
- $this->grav['log']->error('site.routes: '. $pattern . '-> ' . $e->getMessage());
}
}
}
@@ -343,7 +358,8 @@ class Pages
/**
* Get a blueprint for a page type.
*
- * @param string $type
+ * @param string $type
+ *
* @return Blueprint
*/
public function blueprints($type)
@@ -370,6 +386,7 @@ class Pages
* Get all pages
*
* @param \Grav\Common\Page\Page $current
+ *
* @return \Grav\Common\Page\Collection
*/
public function all(Page $current = null)
@@ -380,7 +397,7 @@ class Pages
$current = $current ?: $this->root();
if (!$current->root()) {
- $all[$current->path()] = [ 'slug' => $current->slug() ];
+ $all[$current->path()] = ['slug' => $current->slug()];
}
foreach ($current->children() as $next) {
@@ -394,8 +411,11 @@ class Pages
* Get list of route/title of all pages.
*
* @param Page $current
- * @param int $level
+ * @param int $level
+ * @param bool $rawRoutes
+ *
* @return array
+ *
* @throws \RuntimeException
*/
public function getList(Page $current = null, $level = 0, $rawRoutes = false)
@@ -408,7 +428,7 @@ class Pages
$current = $this->root();
}
- $list = array();
+ $list = [];
if (!$current->root()) {
if ($rawRoutes) {
@@ -416,7 +436,7 @@ class Pages
} else {
$route = $current->route();
}
- $list[$route] = str_repeat(' ', ($level-1)*2) . $current->title();
+ $list[$route] = str_repeat(' ', ($level - 1) * 2) . $current->title();
}
foreach ($current->children() as $next) {
@@ -499,12 +519,12 @@ class Pages
public function accessLevels()
{
$accessLevels = [];
- foreach($this->all() as $page) {
+ foreach ($this->all() as $page) {
if (isset($page->header()->access)) {
if (is_array($page->header()->access)) {
- foreach($page->header()->access as $index => $accessLevel) {
+ foreach ($page->header()->access as $index => $accessLevel) {
if (is_array($accessLevel)) {
- foreach($accessLevel as $innerIndex => $innerAccessLevel) {
+ foreach ($accessLevel as $innerIndex => $innerAccessLevel) {
array_push($accessLevels, $innerIndex);
}
} else {
@@ -529,6 +549,7 @@ class Pages
public static function parents()
{
$rawRoutes = false;
+
return self::getParents($rawRoutes);
}
@@ -540,6 +561,7 @@ class Pages
public static function parentsRawRoutes()
{
$rawRoutes = true;
+
return self::getParents($rawRoutes);
}
@@ -573,17 +595,16 @@ class Pages
}
return $parents;
-
}
/**
- * Get's the home route
+ * Gets the home route
*
* @return string
*/
public static function getHomeRoute()
{
- if (empty(self::$home)) {
+ if (empty(self::$home_route)) {
$grav = Grav::instance();
/** @var Config $config */
@@ -615,6 +636,7 @@ class Pages
self::$home_route = trim($home, '/');
}
+
return self::$home_route;
}
@@ -625,7 +647,7 @@ class Pages
*/
protected function buildPages()
{
- $this->sort = array();
+ $this->sort = [];
/** @var Config $config */
$config = $this->grav['config'];
@@ -656,7 +678,7 @@ class Pages
$last_modified = Folder::lastModifiedFile($pages_dir);
}
- $page_cache_id = md5(USER_DIR.$last_modified.$language->getActive().$config->checksum());
+ $page_cache_id = md5(USER_DIR . $last_modified . $language->getActive() . $config->checksum());
list($this->instances, $this->routes, $this->children, $taxonomy_map, $this->sort) = $cache->fetch($page_cache_id);
if (!$this->instances) {
@@ -689,35 +711,33 @@ class Pages
// cache if needed
if ($this->grav['config']->get('system.cache.enabled')) {
- /** @var Cache $cache */
+ /** @var Cache $cache */
$cache = $this->grav['cache'];
/** @var Taxonomy $taxonomy */
$taxonomy = $this->grav['taxonomy'];
// save pages, routes, taxonomy, and sort to cache
- $cache->save(
- $page_cache_id,
- array($this->instances, $this->routes, $this->children, $taxonomy->taxonomy(), $this->sort)
- );
+ $cache->save($page_cache_id, [$this->instances, $this->routes, $this->children, $taxonomy->taxonomy(), $this->sort]);
}
}
/**
* Recursive function to load & build page relationships.
*
- * @param string $directory
+ * @param string $directory
* @param Page|null $parent
+ *
* @return Page
* @throws \RuntimeException
* @internal
*/
protected function recurse($directory, Page &$parent = null)
{
- $directory = rtrim($directory, DS);
- $page = new Page;
+ $directory = rtrim($directory, DS);
+ $page = new Page;
/** @var Config $config */
- $config = $this->grav['config'];
+ $config = $this->grav['config'];
/** @var Language $language */
$language = $this->grav['language'];
@@ -743,20 +763,21 @@ class Pages
if (!isset($this->instances[$page->path()])) {
$this->instances[$page->path()] = $page;
if ($parent && $page->path()) {
- $this->children[$parent->path()][$page->path()] = array('slug' => $page->slug());
+ $this->children[$parent->path()][$page->path()] = ['slug' => $page->slug()];
}
} else {
throw new \RuntimeException('Fatal error when creating page instances.');
}
$content_exists = false;
- $pages_found = glob($directory.'/*'.CONTENT_EXT);
- $page_extensions = $language->getFallbackPageExtensions();
+ $pages_found = glob($directory . '/*' . CONTENT_EXT);
+ $page_extension = '';
if ($pages_found) {
+ $page_extensions = $language->getFallbackPageExtensions();
foreach ($page_extensions as $extension) {
foreach ($pages_found as $found) {
- if (preg_match('/^.*\/[0-9A-Za-z\-\_]+('.$extension.')$/', $found)) {
+ if (preg_match('/^.*\/[0-9A-Za-z\-\_]+(' . $extension . ')$/', $found)) {
$page_found = $found;
$page_extension = $extension;
break 2;
@@ -800,14 +821,14 @@ class Pages
$page->path($file->getPath());
}
- $path = $directory.DS.$name;
+ $path = $directory . DS . $name;
$child = $this->recurse($path, $page);
if (Utils::startsWith($name, '_')) {
$child->routable(false);
}
- $this->children[$page->path()][$child->path()] = array('slug' => $child->slug());
+ $this->children[$page->path()][$child->path()] = ['slug' => $child->slug()];
if ($config->get('system.pages.events.page')) {
$this->grav->fireEvent('onFolderProcessed', new Event(['page' => $page]));
@@ -833,7 +854,7 @@ class Pages
// Override the modified and ID so that it takes the latest change into account
$page->modified($last_modified);
- $page->id($last_modified.md5($page->filePath()));
+ $page->id($last_modified . md5($page->filePath()));
// Sort based on Defaults or Page Overridden sort order
$this->children[$page->path()] = $this->sort($page);
@@ -859,7 +880,7 @@ class Pages
// process taxonomy
$taxonomy->addTaxonomy($page);
- $route = $page->route();
+ $route = $page->route();
$raw_route = $page->rawRoute();
$page_path = $page->path();
@@ -896,19 +917,20 @@ class Pages
/**
* @param string $path
- * @param array $pages
+ * @param array $pages
* @param string $order_by
- * @param array $manual
+ * @param array $manual
+ *
* @throws \RuntimeException
* @internal
*/
protected function buildSort($path, array $pages, $order_by = 'default', $manual = null)
{
- $list = array();
+ $list = [];
$header_default = null;
$header_query = null;
- // do this headery query work only once
+ // do this header query work only once
if (strpos($order_by, 'header.') === 0) {
$header_query = explode('|', str_replace('header.', '', $order_by));
if (isset($header_query[1])) {
@@ -965,7 +987,7 @@ class Pages
// Move manually ordered items into the beginning of the list. Order of the unlisted items does not change.
if (is_array($manual) && !empty($manual)) {
- $new_list = array();
+ $new_list = [];
$i = count($manual);
foreach ($list as $key => $dummy) {
@@ -974,7 +996,7 @@ class Pages
if ($order === false) {
$order = $i++;
}
- $new_list[$key] = (int) $order;
+ $new_list[$key] = (int)$order;
}
$list = $new_list;
@@ -989,13 +1011,19 @@ class Pages
}
}
- // Shuffles and associative array
+ /**
+ * Shuffles an associative array
+ *
+ * @param array $list
+ *
+ * @return array
+ */
protected function arrayShuffle($list)
{
$keys = array_keys($list);
shuffle($keys);
- $new = array();
+ $new = [];
foreach ($keys as $key) {
$new[$key] = $list[$key];
}
diff --git a/system/src/Grav/Common/Plugin.php b/system/src/Grav/Common/Plugin.php
index 96084b0ed..e6fd41664 100644
--- a/system/src/Grav/Common/Plugin.php
+++ b/system/src/Grav/Common/Plugin.php
@@ -11,7 +11,7 @@ use RocketTheme\Toolbox\File\YamlFile;
/**
* The Plugin object just holds the id and path to a plugin.
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Plugin implements EventSubscriberInterface
@@ -41,7 +41,7 @@ class Plugin implements EventSubscriberInterface
{
$methods = get_class_methods(get_called_class());
- $list = array();
+ $list = [];
foreach ($methods as $method) {
if (strpos($method, 'on') === 0) {
$list[$method] = [$method, 0];
@@ -54,9 +54,9 @@ class Plugin implements EventSubscriberInterface
/**
* Constructor.
*
- * @param string $name
- * @param Grav $grav
- * @param Config $config
+ * @param string $name
+ * @param Grav $grav
+ * @param Config $config
*/
public function __construct($name, Grav $grav, Config $config)
{
@@ -70,6 +70,7 @@ class Plugin implements EventSubscriberInterface
if (isset($this->grav['admin'])) {
return true;
}
+
return false;
}
@@ -83,12 +84,12 @@ class Plugin implements EventSubscriberInterface
foreach ($events as $eventName => $params) {
if (is_string($params)) {
- $dispatcher->addListener($eventName, array($this, $params));
+ $dispatcher->addListener($eventName, [$this, $params]);
} elseif (is_string($params[0])) {
- $dispatcher->addListener($eventName, array($this, $params[0]), isset($params[1]) ? $params[1] : 0);
+ $dispatcher->addListener($eventName, [$this, $params[0]], isset($params[1]) ? $params[1] : 0);
} else {
foreach ($params as $listener) {
- $dispatcher->addListener($eventName, array($this, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
+ $dispatcher->addListener($eventName, [$this, $listener[0]], isset($listener[1]) ? $listener[1] : 0);
}
}
}
@@ -104,12 +105,12 @@ class Plugin implements EventSubscriberInterface
foreach ($events as $eventName => $params) {
if (is_string($params)) {
- $dispatcher->removeListener($eventName, array($this, $params));
+ $dispatcher->removeListener($eventName, [$this, $params]);
} elseif (is_string($params[0])) {
- $dispatcher->removeListener($eventName, array($this, $params[0]));
+ $dispatcher->removeListener($eventName, [$this, $params[0]]);
} else {
foreach ($params as $listener) {
- $dispatcher->removeListener($eventName, array($this, $listener[0]));
+ $dispatcher->removeListener($eventName, [$this, $listener[0]]);
}
}
}
@@ -122,15 +123,16 @@ class Plugin implements EventSubscriberInterface
*
* format: [plugin:myplugin_name](function_data)
*
- * @param $content The string to perform operations upon
- * @param $function The anonymous callback function
- * @param string $internal_regex Optional internal regex to extra data from
+ * @param string $content The string to perform operations upon
+ * @param callable $function The anonymous callback function
+ * @param string $internal_regex Optional internal regex to extra data from
*
* @return string
*/
protected function parseLinks($content, $function, $internal_regex = '(.*)')
{
- $regex = '/\[plugin:(?:'.$this->name.')\]\('.$internal_regex.'\)/i';
+ $regex = '/\[plugin:(?:' . $this->name . ')\]\(' . $internal_regex . '\)/i';
+
return preg_replace_callback($regex, $function, $content);
}
@@ -149,7 +151,7 @@ class Plugin implements EventSubscriberInterface
{
$class_name = $this->name;
$class_name_merged = $class_name . '.merged';
- $defaults = $this->config->get('plugins.'. $class_name, []);
+ $defaults = $this->config->get('plugins.' . $class_name, []);
$page_header = $page->header();
$header = [];
if (!isset($page_header->$class_name_merged) && isset($page_header->$class_name)) {
@@ -180,6 +182,7 @@ class Plugin implements EventSubscriberInterface
} else {
$header = array_merge($header, $params);
}
+
// Return configurations as a new data config class
return new Data($header);
}
@@ -187,11 +190,12 @@ class Plugin implements EventSubscriberInterface
/**
* Persists to disk the plugin parameters currently stored in the Grav Config object
*
- * @param string $plugin_name The name of the plugin whose config it should store.
+ * @param string $plugin_name The name of the plugin whose config it should store.
*
* @return true
*/
- public static function saveConfig($plugin_name) {
+ public static function saveConfig($plugin_name)
+ {
if (!$plugin_name) {
return false;
}
diff --git a/system/src/Grav/Common/Plugins.php b/system/src/Grav/Common/Plugins.php
index de479e138..7088e2ade 100644
--- a/system/src/Grav/Common/Plugins.php
+++ b/system/src/Grav/Common/Plugins.php
@@ -12,7 +12,7 @@ use RocketTheme\Toolbox\Event\EventSubscriberInterface;
* The Plugins object holds an array of all the plugin objects that
* Grav knows about
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Plugins extends Iterator
@@ -29,7 +29,7 @@ class Plugins extends Iterator
{
/** @var Config $config */
$config = self::getGrav()['config'];
- $plugins = (array) $config->get('plugins');
+ $plugins = (array)$config->get('plugins');
$inflector = self::getGrav()['inflector'];
@@ -52,8 +52,8 @@ class Plugins extends Iterator
require_once $filePath;
$pluginClassFormat = [
- 'Grav\\Plugin\\'.ucfirst($plugin).'Plugin',
- 'Grav\\Plugin\\'.$inflector->camelize($plugin).'Plugin'
+ 'Grav\\Plugin\\' . ucfirst($plugin) . 'Plugin',
+ 'Grav\\Plugin\\' . $inflector->camelize($plugin) . 'Plugin'
];
$pluginClassName = false;
@@ -65,7 +65,8 @@ class Plugins extends Iterator
}
if (false === $pluginClassName) {
- throw new \RuntimeException(sprintf("Plugin '%s' class not found! Try reinstalling this plugin.", $plugin));
+ throw new \RuntimeException(sprintf("Plugin '%s' class not found! Try reinstalling this plugin.",
+ $plugin));
}
$instance = new $pluginClassName($plugin, self::getGrav(), $config);
@@ -77,6 +78,11 @@ class Plugins extends Iterator
return $this->items;
}
+ /**
+ * Add a plugin
+ *
+ * @param $plugin
+ */
public function add($plugin)
{
if (is_object($plugin)) {
@@ -91,10 +97,10 @@ class Plugins extends Iterator
*/
public static function all()
{
- $list = array();
+ $list = [];
$locator = Grav::instance()['locator'];
- $plugins = (array) $locator->findResources('plugins://', false);
+ $plugins = (array)$locator->findResources('plugins://', false);
foreach ($plugins as $path) {
$iterator = new \DirectoryIterator($path);
@@ -117,6 +123,13 @@ class Plugins extends Iterator
return $list;
}
+ /**
+ * Get a plugin by name
+ *
+ * @param string $name
+ *
+ * @return Data|null
+ */
public static function get($name)
{
$blueprints = new Blueprints('plugins://');
diff --git a/system/src/Grav/Common/Session.php b/system/src/Grav/Common/Session.php
index bb34d3b2c..c73ddcfca 100644
--- a/system/src/Grav/Common/Session.php
+++ b/system/src/Grav/Common/Session.php
@@ -9,11 +9,19 @@ class Session extends \RocketTheme\Toolbox\Session\Session
protected $grav;
protected $session;
+ /**
+ * Session constructor.
+ *
+ * @param Grav $grav
+ */
public function __construct(Grav $grav)
{
$this->grav = $grav;
}
+ /**
+ * Session init
+ */
public function init()
{
/** @var Uri $uri */
@@ -37,10 +45,7 @@ class Session extends \RocketTheme\Toolbox\Session\Session
if ($config->get('system.session.enabled') || $is_admin) {
// Define session service.
- parent::__construct(
- $session_timeout,
- $session_path
- );
+ parent::__construct($session_timeout, $session_path);
$domain = $uri->host();
if ($domain == 'localhost') {
diff --git a/system/src/Grav/Common/Taxonomy.php b/system/src/Grav/Common/Taxonomy.php
index e280e81f7..ea01c9907 100644
--- a/system/src/Grav/Common/Taxonomy.php
+++ b/system/src/Grav/Common/Taxonomy.php
@@ -22,7 +22,7 @@ use Grav\Common\Page\Page;
* [tag][grav][path/to/item2]
* [tag][dog][path/to/item3]
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Taxonomy
@@ -32,10 +32,12 @@ class Taxonomy
/**
* Constructor that resets the map
+ *
+ * @param Grav $grav
*/
public function __construct(Grav $grav)
{
- $this->taxonomy_map = array();
+ $this->taxonomy_map = [];
$this->grav = $grav;
}
@@ -43,7 +45,7 @@ class Taxonomy
* Takes an individual page and processes the taxonomies configured in its header. It
* then adds those taxonomies to the map
*
- * @param Page $page the page to process
+ * @param Page $page the page to process
* @param array $page_taxonomy
*/
public function addTaxonomy(Page $page, $page_taxonomy = null)
@@ -59,10 +61,10 @@ class Taxonomy
/** @var Config $config */
$config = $this->grav['config'];
if ($config->get('site.taxonomies')) {
- foreach ((array) $config->get('site.taxonomies') as $taxonomy) {
+ foreach ((array)$config->get('site.taxonomies') as $taxonomy) {
if (isset($page_taxonomy[$taxonomy])) {
- foreach ((array) $page_taxonomy[$taxonomy] as $item) {
- $this->taxonomy_map[$taxonomy][(string) $item][$page->path()] = array('slug' => $page->slug());
+ foreach ((array)$page_taxonomy[$taxonomy] as $item) {
+ $this->taxonomy_map[$taxonomy][(string)$item][$page->path()] = ['slug' => $page->slug()];
}
}
}
@@ -73,8 +75,9 @@ class Taxonomy
* Returns a new Page object with the sub-pages containing all the values set for a
* particular taxonomy.
*
- * @param array $taxonomies taxonomies to search, eg ['tag'=>['animal','cat']]
- * @param string $operator can be 'or' or 'and' (defaults to 'or')
+ * @param array $taxonomies taxonomies to search, eg ['tag'=>['animal','cat']]
+ * @param string $operator can be 'or' or 'and' (defaults to 'or')
+ *
* @return Collection Collection object set to contain matches found in the taxonomy map
*/
public function findTaxonomy($taxonomies, $operator = 'and')
@@ -83,7 +86,7 @@ class Taxonomy
$results = [];
foreach ((array)$taxonomies as $taxonomy => $items) {
- foreach ((array) $items as $item) {
+ foreach ((array)$items as $item) {
if (isset($this->taxonomy_map[$taxonomy][$item])) {
$matches[] = $this->taxonomy_map[$taxonomy][$item];
}
@@ -108,6 +111,7 @@ class Taxonomy
* Gets and Sets the taxonomy map
*
* @param array $var the taxonomy map
+ *
* @return array the taxonomy map
*/
public function taxonomy($var = null)
@@ -115,6 +119,7 @@ class Taxonomy
if ($var) {
$this->taxonomy_map = $var;
}
+
return $this->taxonomy_map;
}
}
diff --git a/system/src/Grav/Common/Theme.php b/system/src/Grav/Common/Theme.php
index 2f4ed468c..f76e5f0b7 100644
--- a/system/src/Grav/Common/Theme.php
+++ b/system/src/Grav/Common/Theme.php
@@ -2,7 +2,12 @@
namespace Grav\Common;
use Grav\Common\Config\Config;
+use RocketTheme\Toolbox\File\YamlFile;
+/**
+ * Class Theme
+ * @package Grav\Common
+ */
class Theme extends Plugin
{
public $name;
@@ -10,7 +15,7 @@ class Theme extends Plugin
/**
* Constructor.
*
- * @param Grav $grav
+ * @param Grav $grav
* @param Config $config
* @param string $name
*/
@@ -24,11 +29,12 @@ class Theme extends Plugin
/**
* Persists to disk the theme parameters currently stored in the Grav Config object
*
- * @param string $theme_name The name of the theme whose config it should store.
+ * @param string $theme_name The name of the theme whose config it should store.
*
* @return true
*/
- public static function saveConfig($theme_name) {
+ public static function saveConfig($theme_name)
+ {
if (!$theme_name) {
return false;
}
diff --git a/system/src/Grav/Common/Themes.php b/system/src/Grav/Common/Themes.php
index 2f020f7a4..9f360cc35 100644
--- a/system/src/Grav/Common/Themes.php
+++ b/system/src/Grav/Common/Themes.php
@@ -12,7 +12,7 @@ use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
/**
* The Themes object holds an array of all the theme objects that Grav knows about.
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Themes extends Iterator
@@ -23,6 +23,11 @@ class Themes extends Iterator
/** @var Config */
protected $config;
+ /**
+ * Themes constructor.
+ *
+ * @param Grav $grav
+ */
public function __construct(Grav $grav)
{
parent::__construct();
@@ -51,7 +56,7 @@ class Themes extends Iterator
try {
$instance = $themes->load();
} catch (\InvalidArgumentException $e) {
- throw new \RuntimeException($this->current(). ' theme could not be found');
+ throw new \RuntimeException($this->current() . ' theme could not be found');
}
if ($instance instanceof EventSubscriberInterface) {
@@ -73,10 +78,10 @@ class Themes extends Iterator
*/
public function all()
{
- $list = array();
+ $list = [];
$locator = Grav::instance()['locator'];
- $themes = (array) $locator->findResources('themes://', false);
+ $themes = (array)$locator->findResources('themes://', false);
foreach ($themes as $path) {
$iterator = new \DirectoryIterator($path);
@@ -102,7 +107,8 @@ class Themes extends Iterator
/**
* Get theme configuration or throw exception if it cannot be found.
*
- * @param string $name
+ * @param string $name
+ *
* @return Data
* @throws \RuntimeException
*/
@@ -126,7 +132,9 @@ class Themes extends Iterator
// Find thumbnail.
$thumb = "themes://{$name}/thumbnail.jpg";
- if ($path = $this->grav['locator']->findResource($thumb, false)) {
+ $path = $this->grav['locator']->findResource($thumb, false);
+
+ if ($path) {
$blueprint->set('thumbnail', $this->grav['base_url'] . '/' . $path);
}
@@ -149,7 +157,7 @@ class Themes extends Iterator
*/
public function current()
{
- return (string) $this->config->get('system.pages.theme');
+ return (string)$this->config->get('system.pages.theme');
}
/**
@@ -176,10 +184,9 @@ class Themes extends Iterator
if (!is_object($class)) {
$themeClassFormat = [
- 'Grav\\Theme\\'.ucfirst($name),
- 'Grav\\Theme\\'.$inflector->camelize($name)
+ 'Grav\\Theme\\' . ucfirst($name),
+ 'Grav\\Theme\\' . $inflector->camelize($name)
];
- $themeClassName = false;
foreach ($themeClassFormat as $themeClass) {
if (class_exists($themeClass)) {
@@ -253,8 +260,8 @@ class Themes extends Iterator
/**
* Load theme configuration.
*
- * @param string $name Theme name
- * @param Config $config Configuration class
+ * @param string $name Theme name
+ * @param Config $config Configuration class
*/
protected function loadConfiguration($name, Config $config)
{
@@ -265,7 +272,7 @@ class Themes extends Iterator
/**
* Load theme languages.
*
- * @param Config $config Configuration class
+ * @param Config $config Configuration class
*/
protected function loadLanguages(Config $config)
{
@@ -282,7 +289,7 @@ class Themes extends Iterator
if ($languages) {
$languages = call_user_func_array('array_replace_recursive', $languages);
- $config->getLanguages()->mergeRecursive($languages);
+ $this->grav['languages']->mergeRecursive($languages);
}
}
}
@@ -311,7 +318,7 @@ class Themes extends Iterator
// Load class
if (file_exists($file)) {
- return include_once($file);
+ return include_once($file);
}
}
diff --git a/system/src/Grav/Common/Uri.php b/system/src/Grav/Common/Uri.php
index 235e4c18d..5900622a1 100644
--- a/system/src/Grav/Common/Uri.php
+++ b/system/src/Grav/Common/Uri.php
@@ -6,7 +6,7 @@ use Grav\Common\Page\Page;
/**
* The URI object provides information about the current URL
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Uri
@@ -15,70 +15,211 @@ class Uri
public $url;
- protected $scheme;
- protected $basename;
protected $base;
- protected $root;
+ protected $basename;
protected $bits;
+ protected $content_path;
protected $extension;
protected $host;
- protected $content_path;
+ protected $params;
protected $path;
protected $paths;
- protected $query;
- protected $params;
protected $port;
- protected $uri;
+ protected $query;
+ protected $root;
protected $root_path;
+ protected $uri;
/**
- * Constructor.
+ * Constructor
*/
public function __construct()
{
- $host = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
- // Remove port from HTTP_HOST generated $host
- $host = Utils::substrToString($host, ':');
+ // resets
+ $this->paths = [];
+ $this->params = [];
+ $this->query = [];
+ $this->name = $this->buildHostname();
+ $this->port = $this->buildPort();
+ $this->uri = $this->buildUri();
+ $this->base = $this->buildBaseUrl();
+ $this->host = $this->buildHost();
+ $this->root_path = $this->buildRootPath();
+ $this->root = $this->base . $this->root_path;
+ $this->url = $this->base . $this->uri;
+ }
+
+ /**
+ * Return the hostname from $_SERVER, validated and without port
+ *
+ * @return string
+ */
+ private function buildHostname()
+ {
+ $name = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : (isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : 'localhost');
+
+ // Remove port from HTTP_HOST generated $name
+ $name = Utils::substrToString($name, ':');
// Validate the hostname
- $host = preg_match(Uri::HOSTNAME_REGEX, $host) ? $host : 'unknown';
+ $name = $this->validateHostname($name) ? $name : 'unknown';
- $port = isset($_SERVER['SERVER_PORT']) ? $_SERVER['SERVER_PORT'] : 80;
- $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
+ return $name;
+ }
- $root_path = str_replace(' ', '%20', rtrim(substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], 'index.php')), '/'));
+ /**
+ * Validate a hostname
+ *
+ * @param string $hostname The hostname
+ *
+ * @return boolean
+ */
+ public function validateHostname($hostname)
+ {
+ return (bool)preg_match(Uri::HOSTNAME_REGEX, $hostname);
+ }
+ /**
+ * Get the port from $_SERVER
+ *
+ * @return string
+ */
+ private function buildPort()
+ {
+ $port = isset($_SERVER['SERVER_PORT']) ? (string)$_SERVER['SERVER_PORT'] : '80';
+
+ return $port;
+ }
+
+ /**
+ * Get the Uri from $_SERVER
+ *
+ * @return string
+ */
+ private function buildUri()
+ {
+ $uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '';
+
+ return $uri;
+ }
+
+ /**
+ * Get the base URI with port if needed
+ *
+ * @return string
+ */
+ private function buildBaseUrl()
+ {
// set the base
if (isset($_SERVER['HTTPS'])) {
- $scheme = (strtolower(@$_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://';
+ $base = (strtolower(@$_SERVER['HTTPS']) == 'on') ? 'https://' : 'http://';
} else {
- $scheme = 'http://';
+ $base = 'http://';
}
- // add the sever name
- $base = $scheme . $host;
+ // add the server name
+ $base .= $this->name;
+
+ return $base;
+ }
+
+ /**
+ * Get the Grav Root Path
+ *
+ * @return string
+ */
+ private function buildRootPath()
+ {
+ $root_path = str_replace(' ', '%20', rtrim(substr($_SERVER['PHP_SELF'], 0, strpos($_SERVER['PHP_SELF'], 'index.php')), '/'));
// check if userdir in the path and workaround PHP bug with PHP_SELF
- if (strpos($uri, '/~') !== false && strpos($_SERVER['PHP_SELF'], '/~') === false) {
- $root_path = substr($uri, 0, strpos($uri, '/', 1)) . $root_path;
+ if (strpos($this->uri, '/~') !== false && strpos($_SERVER['PHP_SELF'], '/~') === false) {
+ $root_path = substr($this->uri, 0, strpos($this->uri, '/', 1)) . $root_path;
}
+ return $root_path;
+ }
+
+ /**
+ * Returns the hostname
+ *
+ * @return string
+ */
+ private function buildHost()
+ {
// set hostname
$address = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '::1';
// check for localhost variations
- if ($host == 'localhost' || $address == '::1' || $address == '127.0.0.1') {
- $this->host = 'localhost';
+ if ($this->name == 'localhost' || $address == '::1' || $address == '127.0.0.1') {
+ $host = 'localhost';
} else {
- $this->host = $host;
+ $host = $this->name;
}
- $this->scheme = $scheme;
- $this->port = $port;
- $this->base = $base;
- $this->uri = $uri;
- $this->root_path = $root_path;
+ return $host;
+ }
+ /**
+ * Initialize the URI class with a url passed via parameter.
+ * Used for testing purposes.
+ *
+ * @param string $url the URL to use in the class
+ *
+ * @return string
+ */
+ public function initializeWithUrl($url = '')
+ {
+ if (!$url) {
+ return $this;
+ }
+
+ $this->paths = [];
+ $this->params = [];
+ $this->query = [];
+ $this->name = [];
+ $this->port = [];
+ $this->uri = [];
+ $this->base = [];
+ $this->host = [];
+ $this->root = [];
+ $this->url = [];
+
+ $params = parse_url($url);
+
+ $this->name = $params['host'];
+ $this->port = isset($params['port']) ? $params['port'] : '80';
+
+ $this->uri = $params['path'];
+ if (isset($params['query'])) {
+ $this->uri .= '?' . $params['query'];
+ parse_str($params['query'], $this->query);
+ }
+
+ $this->base = $this->buildBaseUrl();
+ $this->host = $this->buildHost();
+ $this->root_path = $this->buildRootPath();
+ $this->root = $this->base . $this->root_path;
+ $this->url = $this->base . $this->uri;
+
+ return $this;
+ }
+
+ /**
+ * Initialize the URI class by providing url and root_path arguments
+ *
+ * @param string $url
+ * @param string $root_path
+ *
+ * @return $this
+ */
+ public function initializeWithUrlAndRootPath($url, $root_path)
+ {
+ $this->initializeWithUrl($url);
+ $this->root_path = $root_path;
+ $this->root = $this->base . $this->root_path;
+
+ return $this;
}
/**
@@ -91,14 +232,9 @@ class Uri
$config = $grav['config'];
$language = $grav['language'];
- // resets
- $this->paths = [];
- $this->params = [];
- $this->query = [];
-
// add the port to the base for non-standard ports
if ($config->get('system.reverse_proxy_setup') == false && $this->port != '80' && $this->port != '443') {
- $this->base .= ":".$this->port;
+ $this->base .= ":" . $this->port;
}
// Set some defaults
@@ -133,7 +269,9 @@ class Uri
// process query string
if (isset($bits['query']) && isset($bits['path'])) {
- $this->query = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
+ if (!$this->query) {
+ $this->query = filter_input_array(INPUT_GET, FILTER_SANITIZE_STRING);
+ }
$uri = $bits['path'];
}
@@ -151,8 +289,8 @@ class Uri
$valid_page_types = implode('|', $config->get('system.pages.types'));
// Strip the file extension for valid page types
- if (preg_match("/\.(".$valid_page_types.")$/", $parts['basename'])) {
- $uri = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, $parts['dirname']), DS). '/' .$parts['filename'];
+ if (preg_match("/\.(" . $valid_page_types . ")$/", $parts['basename'])) {
+ $uri = rtrim(str_replace(DIRECTORY_SEPARATOR, DS, $parts['dirname']), DS) . '/' . $parts['filename'];
}
// set the new url
@@ -176,7 +314,7 @@ class Uri
{
if (strpos($uri, $delimiter) !== false) {
$bits = explode('/', $uri);
- $path = array();
+ $path = [];
foreach ($bits as $bit) {
if (strpos($bit, $delimiter) !== false) {
$param = explode($delimiter, $bit);
@@ -190,13 +328,15 @@ class Uri
}
$uri = '/' . ltrim(implode('/', $path), '/');
}
+
return $uri;
}
/**
* Return URI path.
*
- * @param string $id
+ * @param string $id
+ *
* @return string
*/
public function paths($id = null)
@@ -211,8 +351,9 @@ class Uri
/**
* Return route to the current URI. By default route doesn't include base path.
*
- * @param bool $absolute True to include full path.
- * @param bool $domain True to include domain. Works only if first parameter is also true.
+ * @param bool $absolute True to include full path.
+ * @param bool $domain True to include domain. Works only if first parameter is also true.
+ *
* @return string
*/
public function route($absolute = false, $domain = false)
@@ -223,8 +364,10 @@ class Uri
/**
* Return full query string or a single query attribute.
*
- * @param string $id Optional attribute.
- * @return string
+ * @param string $id Optional attribute. Get a single query attribute if set
+ * @param bool $raw If true and $id is not set, return the full query array. Otherwise return the query string
+ *
+ * @return string|array Returns an array if $id = null and $raw = true
*/
public function query($id = null, $raw = false)
{
@@ -234,6 +377,10 @@ class Uri
if ($raw) {
return $this->query;
} else {
+ if (!$this->query) {
+ return '';
+ }
+
return http_build_query($this->query);
}
}
@@ -242,8 +389,9 @@ class Uri
/**
* Return all or a single query parameter as a URI compatible string.
*
- * @param string $id Optional parameter name.
+ * @param string $id Optional parameter name.
* @param boolean $array return the array format or not
+ *
* @return null|string
*/
public function params($id = null, $array = false)
@@ -255,16 +403,16 @@ class Uri
if ($array) {
return $this->params;
}
- $output = array();
+ $output = [];
foreach ($this->params as $key => $value) {
$output[] = $key . $config->get('system.param_sep') . $value;
- $params = '/'.implode('/', $output);
+ $params = '/' . implode('/', $output);
}
} elseif (isset($this->params[$id])) {
if ($array) {
return $this->params[$id];
}
- $params = "/{$id}". $config->get('system.param_sep') . $this->params[$id];
+ $params = "/{$id}" . $config->get('system.param_sep') . $this->params[$id];
}
return $params;
@@ -273,7 +421,8 @@ class Uri
/**
* Get URI parameter.
*
- * @param string $id
+ * @param string $id
+ *
* @return bool|string
*/
public function param($id)
@@ -288,7 +437,8 @@ class Uri
/**
* Return URL.
*
- * @param bool $include_host Include hostname.
+ * @param bool $include_host Include hostname.
+ *
* @return string
*/
public function url($include_host = false)
@@ -297,6 +447,7 @@ class Uri
return $this->url;
} else {
$url = (str_replace($this->base, '', rtrim($this->url, '/')));
+
return $url ? $url : '/';
}
}
@@ -312,6 +463,7 @@ class Uri
if ($path === '') {
$path = '/';
}
+
return $path;
}
@@ -327,17 +479,8 @@ class Uri
if (!$this->extension) {
$this->extension = $default;
}
- return $this->extension;
- }
- /**
- * Return the scheme of the URI
- *
- * @return String The scheme of the URI
- */
- public function scheme()
- {
- return $this->scheme;
+ return $this->extension;
}
/**
@@ -391,11 +534,11 @@ class Uri
return $this->base;
}
-
/**
* Return root URL to the site.
*
- * @param bool $include_host Include hostname.
+ * @param bool $include_host Include hostname.
+ *
* @return mixed
*/
public function rootUrl($include_host = false)
@@ -404,6 +547,7 @@ class Uri
return $this->root;
} else {
$root = str_replace($this->base, '', $this->root);
+
return $root;
}
}
@@ -427,6 +571,7 @@ class Uri
*
* @param string $default
* @param string $attributes
+ *
* @return string
*/
public function referrer($default = null, $attributes = null)
@@ -482,7 +627,8 @@ class Uri
/**
* Is this an external URL? if it starts with `http` then yes, else false
*
- * @param string $url the URL in question
+ * @param string $url the URL in question
+ *
* @return boolean is eternal state
*/
public function isExternal($url)
@@ -498,6 +644,7 @@ class Uri
* The opposite of built-in PHP method parse_url()
*
* @param $parsed_url
+ *
* @return string
*/
public static function buildUrl($parsed_url)
@@ -511,16 +658,17 @@ class Uri
$path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
$query = isset($parsed_url['query']) ? '?' . $parsed_url['query'] : '';
$fragment = isset($parsed_url['fragment']) ? '#' . $parsed_url['fragment'] : '';
+
return "$scheme$user$pass$host$port$path$query$fragment";
}
/**
- * Converts links from absolute '/' or relative (../..) to a grav friendly format
+ * Converts links from absolute '/' or relative (../..) to a Grav friendly format
*
- * @param Page|the $page the current page to use as reference
- * @param string $markdown_url the URL as it was written in the markdown
- * @param string $type the type of URL, image | link
- * @param null $relative if null, will use system default, if true will use relative links internally
+ * @param Page $page the current page to use as reference
+ * @param string $markdown_url the URL as it was written in the markdown
+ * @param string $type the type of URL, image | link
+ * @param null $relative if null, will use system default, if true will use relative links internally
*
* @return string the more friendly formatted url
*/
@@ -528,7 +676,6 @@ class Uri
{
$grav = Grav::instance();
- /** @var Grav\Common\Language\Language $language */
$language = $grav['language'];
// Link processing should prepend language
@@ -541,7 +688,7 @@ class Uri
if (is_null($relative)) {
$base = $grav['base_url'];
} else {
- $base = $relative ? $grav['base_url_relative'] : $grav['base_url_absolute'];
+ $base = $relative ? $grav['base_url_relative'] : $grav['base_url_absolute'];
}
$base_url = rtrim($base . $grav['pages']->base(), '/') . $language_append;
@@ -587,7 +734,6 @@ class Uri
$page_path = $path_info['dirname'];
$filename = '';
-
if ($markdown_url == '..') {
$page_path = $full_path;
} else {
@@ -604,8 +750,10 @@ class Uri
// get page instances and try to find one that fits
$instances = $grav['pages']->instances();
if (isset($instances[$page_path])) {
+ /** @var Page $target */
$target = $instances[$page_path];
$url_bits['path'] = $base_url . rtrim($target->route(), '/') . $filename;
+
return Uri::buildUrl($url_bits);
}
@@ -616,8 +764,8 @@ class Uri
/**
* Adds the nonce to a URL for a specific action
*
- * @param string $url the url
- * @param string $action the action
+ * @param string $url the url
+ * @param string $action the action
* @param string $nonceParamName the param name to use
*
* @return string the url with the nonce
@@ -625,7 +773,7 @@ class Uri
public static function addNonce($url, $action, $nonceParamName = 'nonce')
{
$urlWithNonce = $url . '/' . $nonceParamName . Grav::instance()['config']->get('system.param_sep', ':') . Utils::getNonce($action);
+
return $urlWithNonce;
}
-
}
diff --git a/system/src/Grav/Common/User/Authentication.php b/system/src/Grav/Common/User/Authentication.php
index fc26bf8d7..4d3660385 100644
--- a/system/src/Grav/Common/User/Authentication.php
+++ b/system/src/Grav/Common/User/Authentication.php
@@ -4,7 +4,7 @@ namespace Grav\Common\User;
/**
* User authentication
*
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
abstract class Authentication
@@ -12,7 +12,8 @@ abstract class Authentication
/**
* Create password hash from plaintext password.
*
- * @param string $password Plaintext password.
+ * @param string $password Plaintext password.
+ *
* @throws \RuntimeException
* @return string|bool
*/
@@ -34,8 +35,9 @@ abstract class Authentication
/**
* Verifies that a password matches a hash.
*
- * @param string $password Plaintext password.
- * @param string $hash Hash to verify against.
+ * @param string $password Plaintext password.
+ * @param string $hash Hash to verify against.
+ *
* @return int Returns 0 if the check fails, 1 if password matches, 2 if hash needs to be updated.
*/
public static function verify($password, $hash)
diff --git a/system/src/Grav/Common/User/Group.php b/system/src/Grav/Common/User/Group.php
index 965fde5f6..0a424f418 100644
--- a/system/src/Grav/Common/User/Group.php
+++ b/system/src/Grav/Common/User/Group.php
@@ -10,10 +10,7 @@ use Grav\Common\Utils;
/**
* Group object
*
- * @property mixed authenticated
- * @property mixed password
- * @property bool|string hashed_password
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class Group extends Data
@@ -28,12 +25,15 @@ class Group extends Data
private static function groups()
{
$groups = self::getGrav()['config']->get('groups');
+
return $groups;
}
/**
* Checks if a group exists
*
+ * @param string $groupname
+ *
* @return object
*/
public static function group_exists($groupname)
@@ -44,6 +44,8 @@ class Group extends Data
/**
* Get a group by name
*
+ * @param string $groupname
+ *
* @return object
*/
public static function load($groupname)
@@ -76,7 +78,7 @@ class Group extends Data
self::getGrav()['config']->set("groups.$this->groupname", []);
- foreach($fields as $field) {
+ foreach ($fields as $field) {
if ($field['type'] == 'text') {
$value = $field['name'];
if (isset($this->items[$value])) {
@@ -87,8 +89,10 @@ class Group extends Data
$value = $field['name'];
$arrayValues = Utils::resolve($this->items, $field['name']);
- if ($arrayValues) foreach($arrayValues as $arrayIndex => $arrayValue) {
- self::getGrav()['config']->set("groups.$this->groupname.$value.$arrayIndex", $arrayValue);
+ if ($arrayValues) {
+ foreach ($arrayValues as $arrayIndex => $arrayValue) {
+ self::getGrav()['config']->set("groups.$this->groupname.$value.$arrayIndex", $arrayValue);
+ }
}
}
}
@@ -104,7 +108,8 @@ class Group extends Data
/**
* Remove a group
*
- * @param string $username
+ * @param string $groupname
+ *
* @return bool True if the action was performed
*/
public static function remove($groupname)
diff --git a/system/src/Grav/Common/User/User.php b/system/src/Grav/Common/User/User.php
index 4ba6a20c4..da51c1235 100644
--- a/system/src/Grav/Common/User/User.php
+++ b/system/src/Grav/Common/User/User.php
@@ -10,10 +10,10 @@ use Grav\Common\Utils;
/**
* User object
*
- * @property mixed authenticated
- * @property mixed password
+ * @property mixed authenticated
+ * @property mixed password
* @property bool|string hashed_password
- * @author RocketTheme
+ * @author RocketTheme
* @license MIT
*/
class User extends Data
@@ -26,6 +26,7 @@ class User extends Data
* Always creates user object. To check if user exists, use $this->exists().
*
* @param string $username
+ *
* @return User
*/
public static function load($username)
@@ -56,6 +57,7 @@ class User extends Data
* Remove user account.
*
* @param string $username
+ *
* @return bool True if the action was performed
*/
public static function remove($username)
@@ -73,7 +75,8 @@ class User extends Data
*
* If user password needs to be updated, new information will be saved.
*
- * @param string $password Plaintext password.
+ * @param string $password Plaintext password.
+ *
* @return bool
*/
public function authenticate($password)
@@ -88,8 +91,9 @@ class User extends Data
// the result
Authentication::verify(
$password,
- self::getGrav()['config']->get('system.security.default_hash', '$2y$10$kwsyMVwM8/7j0K/6LHT.g.Fs49xOCTp2b8hh/S5.dPJuJcJB6T.UK')
+ self::getGrav()['config']->get('system.security.default_hash')
);
+
return false;
} else {
// Plain-text does match, we can update the hash and proceed
@@ -113,7 +117,7 @@ class User extends Data
$this->save();
}
- return (bool) $result;
+ return (bool)$result;
}
/**
@@ -139,7 +143,8 @@ class User extends Data
/**
* Checks user authorization to the action.
*
- * @param string $action
+ * @param string $action
+ *
* @return bool
*/
public function authorize($action)
@@ -156,21 +161,22 @@ class User extends Data
//Check group access level
$groups = $this->get('groups');
- if ($groups) foreach($groups as $group) {
- $permission = self::getGrav()['config']->get("groups.{$group}.access.{$action}");
- if (Utils::isPositive($permission)) {
- $return = true;
+ if ($groups) {
+ foreach ((array)$groups as $group) {
+ $permission = self::getGrav()['config']->get("groups.{$group}.access.{$action}");
+ $return = Utils::isPositive($permission);
+ if ($return === true) {
+ break;
+ }
}
}
//Check user access level
- if (!$this->get('access')) {
- return false;
- }
-
- if (Utils::resolve($this->get('access'), $action) !== null) {
- $permission = $this->get("access.{$action}");
- $return = Utils::isPositive($permission);
+ if ($this->get('access')) {
+ if (Utils::resolve($this->get('access'), $action) !== null) {
+ $permission = $this->get("access.{$action}");
+ $return = Utils::isPositive($permission);
+ }
}
return $return;
@@ -181,6 +187,7 @@ class User extends Data
* Ensures backwards compatibility
*
* @param string $action
+ *
* @deprecated use authorize()
* @return bool
*/
diff --git a/system/src/Grav/Common/Utils.php b/system/src/Grav/Common/Utils.php
index 396fc7b2b..597bae22a 100644
--- a/system/src/Grav/Common/Utils.php
+++ b/system/src/Grav/Common/Utils.php
@@ -18,6 +18,8 @@ abstract class Utils
protected static $nonces = [];
/**
+ * Check if the $haystack string starts with the substring $needle
+ *
* @param string $haystack
* @param string $needle
*
@@ -41,6 +43,8 @@ abstract class Utils
}
/**
+ * Check if the $haystack string ends with the substring $needle
+ *
* @param string $haystack
* @param string $needle
*
@@ -64,6 +68,8 @@ abstract class Utils
}
/**
+ * Check if the $haystack string contains the substring $needle
+ *
* @param string $haystack
* @param string $needle
*
@@ -79,13 +85,15 @@ abstract class Utils
*
* @param $haystack
* @param $needle
+ *
* @return string
*/
public static function substrToString($haystack, $needle)
{
if (static::contains($haystack, $needle)) {
- return substr($haystack, 0, strpos($haystack,$needle));
+ return substr($haystack, 0, strpos($haystack, $needle));
}
+
return $haystack;
}
@@ -103,6 +111,8 @@ abstract class Utils
}
/**
+ * Return the Grav date formats allowed
+ *
* @return array
*/
public static function dateFormats()
@@ -120,6 +130,7 @@ abstract class Utils
if ($default_format) {
$date_formats = array_merge([$default_format => $default_format.' (e.g. '.$now->format($default_format).')'], $date_formats);
}
+
return $date_formats;
}
@@ -127,10 +138,11 @@ abstract class Utils
* Truncate text by number of characters but can cut off words.
*
* @param string $string
- * @param int $limit Max number of characters.
- * @param bool $up_to_break truncate up to breakpoint after char count
- * @param string $break Break point.
- * @param string $pad Appended padding to the end of the string.
+ * @param int $limit Max number of characters.
+ * @param bool $up_to_break truncate up to breakpoint after char count
+ * @param string $break Break point.
+ * @param string $pad Appended padding to the end of the string.
+ *
* @return string
*/
public static function truncate($string, $limit = 150, $up_to_break = false, $break = " ", $pad = "…")
@@ -155,8 +167,9 @@ abstract class Utils
/**
* Truncate text by number of characters in a "word-safe" manor.
*
- * @param $string
- * @param int $limit
+ * @param string $string
+ * @param int $limit
+ *
* @return string
*/
public static function safeTruncate($string, $limit = 150)
@@ -175,7 +188,7 @@ abstract class Utils
*/
public static function truncateHtml($text, $length = 100)
{
- return Truncator::truncate($text, $length, array('length_in_chars' => true));
+ return Truncator::truncate($text, $length, ['length_in_chars' => true]);
}
/**
@@ -188,7 +201,7 @@ abstract class Utils
*/
public static function safeTruncateHtml($text, $length = 100)
{
- return Truncator::truncate($text, $length, array('length_in_chars' => true, 'word_safe' => true));
+ return Truncator::truncate($text, $length, ['length_in_chars' => true, 'word_safe' => true]);
}
/**
@@ -206,8 +219,8 @@ abstract class Utils
/**
* Provides the ability to download a file to the browser
*
- * @param $file the full path to the file to be downloaded
- * @param bool $force_download as opposed to letting browser choose if to download or render
+ * @param string $file the full path to the file to be downloaded
+ * @param bool $force_download as opposed to letting browser choose if to download or render
*/
public static function download($file, $force_download = true)
{
@@ -223,7 +236,8 @@ abstract class Utils
if (!Utils::isFunctionDisabled('set_time_limit') && !ini_get('safe_mode') && function_exists('set_time_limit')) {
set_time_limit(0);
}
- } catch (\Exception $e) {}
+ } catch (\Exception $e) {
+ }
ignore_user_abort(false);
@@ -264,7 +278,7 @@ abstract class Utils
/**
* Return the mimetype based on filename
*
- * @param $extension Extension of file (eg .txt)
+ * @param string $extension Extension of file (eg "txt")
*
* @return string
*/
@@ -283,7 +297,7 @@ abstract class Utils
/**
* Normalize path by processing relative `.` and `..` syntax and merging path
*
- * @param $path
+ * @param string $path
*
* @return string
*/
@@ -292,7 +306,7 @@ abstract class Utils
$root = ($path[0] === '/') ? '/' : '';
$segments = explode('/', trim($path, '/'));
- $ret = array();
+ $ret = [];
foreach ($segments as $segment) {
if (($segment == '.') || empty($segment)) {
continue;
@@ -308,7 +322,9 @@ abstract class Utils
}
/**
- * @param $function
+ * Check whether a function is disabled in the PHP settings
+ *
+ * @param string $function the name of the function to check
*
* @return bool
*/
@@ -318,6 +334,8 @@ abstract class Utils
}
/**
+ * Get the formatted timezones list
+ *
* @return array
*/
public static function timezones()
@@ -333,7 +351,7 @@ abstract class Utils
asort($offsets);
- $timezone_list = array();
+ $timezone_list = [];
foreach ($offsets as $timezone => $offset) {
$offset_prefix = $offset < 0 ? '-' : '+';
$offset_formatted = gmdate('H:i', abs($offset));
@@ -344,41 +362,46 @@ abstract class Utils
}
return $timezone_list;
-
}
/**
- * @param array $source
- * @param $fn
+ * Recursively filter an array, filtering values by processing them through the $fn function argument
+ *
+ * @param array $source the Array to filter
+ * @param callable $fn the function to pass through each array item
*
* @return array
*/
public static function arrayFilterRecursive(Array $source, $fn)
{
- $result = array();
- foreach ($source as $key => $value)
- {
- if (is_array($value))
- {
+ $result = [];
+ foreach ($source as $key => $value) {
+ if (is_array($value)) {
$result[$key] = static::arrayFilterRecursive($value, $fn);
continue;
}
- if ($fn($key, $value))
- {
+ if ($fn($key, $value)) {
$result[$key] = $value; // KEEP
continue;
}
}
+
return $result;
}
/**
- * @param $string
+ * Checks if the passed path contains the language code prefix
+ *
+ * @param string $string The path
*
* @return bool
*/
public static function pathPrefixedByLangCode($string)
{
+ if (strlen($string) <= 3) {
+ return false;
+ }
+
$languages_enabled = self::getGrav()['config']->get('system.languages.supported', []);
if ($string[0] == '/' && $string[3] == '/' && in_array(substr($string, 1, 2), $languages_enabled)) {
@@ -389,9 +412,12 @@ abstract class Utils
}
/**
- * @param $date
+ * Get the timestamp of a date
*
- * @return int
+ * @param string $date a String expressed in the system.pages.dateformat.default format, with fallback to a
+ * strtotime argument
+ *
+ * @return int the timestamp
*/
public static function date2timestamp($date)
{
@@ -414,7 +440,13 @@ abstract class Utils
}
/**
- * Get value of an array using dot notation
+ * Get value of an array element using dot notation
+ *
+ * @param array $array the Array to check
+ * @param string $path the dot notation path to check
+ * @param mixed $default a value to be returned if $path is not found in $array
+ *
+ * @return mixed the value found
*/
public static function resolve(array $array, $path, $default = null)
{
@@ -450,7 +482,7 @@ abstract class Utils
* with reverse proxy setups.
*
* @param string $action
- * @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
+ * @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
*
* @return string the nonce string
*/
@@ -469,7 +501,7 @@ abstract class Utils
$i++;
}
- return ( $i . '|' . $action . '|' . $username . '|' . $token . '|' . self::getGrav()['config']->get('security.salt'));
+ return ($i . '|' . $action . '|' . $username . '|' . $token . '|' . self::getGrav()['config']->get('security.salt'));
}
//Added in version 1.0.8 to ensure that existing nonces are not broken.
@@ -490,7 +522,8 @@ abstract class Utils
if ($plusOneTick) {
$i++;
}
- return ( $i . '|' . $action . '|' . $username . '|' . $token . '|' . self::getGrav()['config']->get('security.salt'));
+
+ return ($i . '|' . $action . '|' . $username . '|' . $token . '|' . self::getGrav()['config']->get('security.salt'));
}
/**
@@ -504,15 +537,16 @@ abstract class Utils
private static function nonceTick()
{
$secondsInHalfADay = 60 * 60 * 12;
- return (int)ceil(time() / ( $secondsInHalfADay ));
+
+ return (int)ceil(time() / ($secondsInHalfADay));
}
/**
* Creates a hashed nonce tied to the passed action. Tied to the current user and time. The nonce for a given
* action is the same for 12 hours.
*
- * @param string $action the action the nonce is tied to (e.g. save-user-admin or move-page-homepage)
- * @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
+ * @param string $action the action the nonce is tied to (e.g. save-user-admin or move-page-homepage)
+ * @param bool $plusOneTick if true, generates the token for the next tick (the next 12 hours)
*
* @return string the nonce
*/
@@ -545,7 +579,7 @@ abstract class Utils
/**
* Verify the passed nonce for the give action
*
- * @param string $nonce the nonce to verify
+ * @param string $nonce the nonce to verify
* @param string $action the action to verify the nonce to
*
* @return boolean verified or not
diff --git a/system/src/Grav/Console/Cli/CleanCommand.php b/system/src/Grav/Console/Cli/CleanCommand.php
index adcf87638..ff6d28614 100644
--- a/system/src/Grav/Console/Cli/CleanCommand.php
+++ b/system/src/Grav/Console/Cli/CleanCommand.php
@@ -24,6 +24,8 @@ class CleanCommand extends Command
* @var array
*/
protected $paths_to_remove = [
+ 'codeception.yml',
+ 'tests/',
'user/plugins/email/vendor/swiftmailer/swiftmailer/.travis.yml',
'user/plugins/email/vendor/swiftmailer/swiftmailer/build.xml',
'user/plugins/email/vendor/swiftmailer/swiftmailer/composer.json',
diff --git a/system/src/Grav/Console/Cli/SandboxCommand.php b/system/src/Grav/Console/Cli/SandboxCommand.php
index de965df5e..be692dc02 100644
--- a/system/src/Grav/Console/Cli/SandboxCommand.php
+++ b/system/src/Grav/Console/Cli/SandboxCommand.php
@@ -55,6 +55,7 @@ class SandboxCommand extends ConsoleCommand
'/system' => '/system',
'/vendor' => '/vendor',
'/webserver-configs' => '/webserver-configs',
+ '/codeception.yml' => '/codeception.yml',
);
/**
diff --git a/tests/_bootstrap.php b/tests/_bootstrap.php
new file mode 100644
index 000000000..725400db8
--- /dev/null
+++ b/tests/_bootstrap.php
@@ -0,0 +1,49 @@
+bin/grav install");
+}
+
+use Grav\Common\Grav;
+
+// Register the auto-loader.
+$loader = require_once $autoload;
+
+if (version_compare($ver = PHP_VERSION, $req = GRAV_PHP_MIN, '<')) {
+ throw new \RuntimeException(sprintf('You are running PHP %s, but Grav needs at least PHP %s to run.', $ver, $req));
+}
+
+// Set timezone to default, falls back to system if php.ini not set
+date_default_timezone_set(@date_default_timezone_get());
+
+// Set internal encoding if mbstring loaded
+if (!extension_loaded('mbstring')) {
+ throw new \RuntimeException("'mbstring' extension is not loaded. This is required for Grav to run correctly");
+}
+mb_internal_encoding('UTF-8');
+
+// Get the Grav instance
+$grav = Grav::instance(
+ array(
+ 'loader' => $loader
+ )
+);
+
+$grav['debugger']->init();
+$grav['assets']->init();
+
+// Set default $_SERVER value used for nonces
+empty( $_SERVER['HTTP_CLIENT_IP'] ) && $_SERVER['HTTP_CLIENT_IP'] = '127.0.0.1';
+
+$fake = Factory::create();
+Fixtures::add('grav', $grav);
+Fixtures::add('fake', $fake);
\ No newline at end of file
diff --git a/tests/_support/AcceptanceTester.php b/tests/_support/AcceptanceTester.php
new file mode 100644
index 000000000..4c7dcbb6d
--- /dev/null
+++ b/tests/_support/AcceptanceTester.php
@@ -0,0 +1,26 @@
+setHeader('X-Requested-With', 'Codeception');
+ * $I->amOnPage('test-headers.php');
+ * ?>
+ * ```
+ *
+ * @param string $name the name of the request header
+ * @param string $value the value to set it to for subsequent
+ * requests
+ * @see \Codeception\Module\PhpBrowser::setHeader()
+ */
+ public function setHeader($name, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('setHeader', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Deletes the header with the passed name. Subsequent requests
+ * will not have the deleted header in its request.
+ *
+ * Example:
+ * ```php
+ * setHeader('X-Requested-With', 'Codeception');
+ * $I->amOnPage('test-headers.php');
+ * // ...
+ * $I->deleteHeader('X-Requested-With');
+ * $I->amOnPage('some-other-page.php');
+ * ?>
+ * ```
+ *
+ * @param string $name the name of the header to delete.
+ * @see \Codeception\Module\PhpBrowser::deleteHeader()
+ */
+ public function deleteHeader($name) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteHeader', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Authenticates user for HTTP_AUTH
+ *
+ * @param $username
+ * @param $password
+ * @see \Codeception\Module\PhpBrowser::amHttpAuthenticated()
+ */
+ public function amHttpAuthenticated($username, $password) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Condition('amHttpAuthenticated', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Open web page at the given absolute URL and sets its hostname as the base host.
+ *
+ * ``` php
+ * amOnUrl('http://codeception.com');
+ * $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart
+ * ?>
+ * ```
+ * @see \Codeception\Module\PhpBrowser::amOnUrl()
+ */
+ public function amOnUrl($url) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnUrl', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Changes the subdomain for the 'url' configuration parameter.
+ * Does not open a page; use `amOnPage` for that.
+ *
+ * ``` php
+ * amOnSubdomain('user');
+ * $I->amOnPage('/');
+ * // moves to http://user.mysite.com/
+ * ?>
+ * ```
+ *
+ * @param $subdomain
+ *
+ * @return mixed
+ * @see \Codeception\Module\PhpBrowser::amOnSubdomain()
+ */
+ public function amOnSubdomain($subdomain) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnSubdomain', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Low-level API method.
+ * If Codeception commands are not enough, use [Guzzle HTTP Client](http://guzzlephp.org/) methods directly
+ *
+ * Example:
+ *
+ * ``` php
+ * executeInGuzzle(function (\GuzzleHttp\Client $client) {
+ * $client->get('/get', ['query' => ['foo' => 'bar']]);
+ * });
+ * ?>
+ * ```
+ *
+ * It is not recommended to use this command on a regular basis.
+ * If Codeception lacks important Guzzle Client methods, implement them and submit patches.
+ *
+ * @param callable $function
+ * @see \Codeception\Module\PhpBrowser::executeInGuzzle()
+ */
+ public function executeInGuzzle($function) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('executeInGuzzle', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Opens the page for the given relative URI.
+ *
+ * ``` php
+ * amOnPage('/');
+ * // opens /register page
+ * $I->amOnPage('/register');
+ * ```
+ *
+ * @param $page
+ * @see \Codeception\Lib\InnerBrowser::amOnPage()
+ */
+ public function amOnPage($page) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnPage', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Perform a click on a link or a button, given by a locator.
+ * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string.
+ * For buttons, the "value" attribute, "name" attribute, and inner text are searched.
+ * For links, the link text is searched.
+ * For images, the "alt" attribute and inner text of any parent links are searched.
+ *
+ * The second parameter is a context (CSS or XPath locator) to narrow the search.
+ *
+ * Note that if the locator matches a button of type `submit`, the form will be submitted.
+ *
+ * ``` php
+ * click('Logout');
+ * // button of form
+ * $I->click('Submit');
+ * // CSS button
+ * $I->click('#form input[type=submit]');
+ * // XPath
+ * $I->click('//form/*[@type=submit]');
+ * // link in context
+ * $I->click('Logout', '#nav');
+ * // using strict locator
+ * $I->click(['link' => 'Login']);
+ * ?>
+ * ```
+ *
+ * @param $link
+ * @param $context
+ * @see \Codeception\Lib\InnerBrowser::click()
+ */
+ public function click($link, $context = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('click', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string (case insensitive).
+ *
+ * You can specify a specific HTML element (via CSS or XPath) as the second
+ * parameter to only search within that element.
+ *
+ * ``` php
+ * see('Logout'); // I can suppose user is logged in
+ * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
+ * $I->see('Sign Up', '//body/h1'); // with XPath
+ * ```
+ *
+ * Note that the search is done after stripping all HTML tags from the body,
+ * so `$I->see('strong')` will return true for strings like:
+ *
+ * - `
I am Stronger than thou
`
+ * - ``
+ *
+ * But will *not* be true for strings like:
+ *
+ * - `Home`
+ * - `
Home`
+ * - ``
+ *
+ * For checking the raw source code, use `seeInSource()`.
+ *
+ * @param $text
+ * @param null $selector
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::see()
+ */
+ public function canSee($text, $selector = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('see', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string (case insensitive).
+ *
+ * You can specify a specific HTML element (via CSS or XPath) as the second
+ * parameter to only search within that element.
+ *
+ * ``` php
+ * see('Logout'); // I can suppose user is logged in
+ * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page
+ * $I->see('Sign Up', '//body/h1'); // with XPath
+ * ```
+ *
+ * Note that the search is done after stripping all HTML tags from the body,
+ * so `$I->see('strong')` will return true for strings like:
+ *
+ * - `
I am Stronger than thou
`
+ * - ``
+ *
+ * But will *not* be true for strings like:
+ *
+ * - `Home`
+ * - `
Home`
+ * - ``
+ *
+ * For checking the raw source code, use `seeInSource()`.
+ *
+ * @param $text
+ * @param null $selector
+ * @see \Codeception\Lib\InnerBrowser::see()
+ */
+ public function see($text, $selector = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('see', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page doesn't contain the text specified (case insensitive).
+ * Give a locator as the second parameter to match a specific region.
+ *
+ * ```php
+ * dontSee('Login'); // I can suppose user is already logged in
+ * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
+ * $I->dontSee('Sign Up','//body/h1'); // with XPath
+ * ```
+ *
+ * Note that the search is done after stripping all HTML tags from the body,
+ * so `$I->dontSee('strong')` will fail on strings like:
+ *
+ * - `
Home`
+ * - ``
+ *
+ * For checking the raw source code, use `seeInSource()`.
+ *
+ * @param $text
+ * @param null $selector
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSee()
+ */
+ public function cantSee($text, $selector = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSee', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page doesn't contain the text specified (case insensitive).
+ * Give a locator as the second parameter to match a specific region.
+ *
+ * ```php
+ * dontSee('Login'); // I can suppose user is already logged in
+ * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page
+ * $I->dontSee('Sign Up','//body/h1'); // with XPath
+ * ```
+ *
+ * Note that the search is done after stripping all HTML tags from the body,
+ * so `$I->dontSee('strong')` will fail on strings like:
+ *
+ * - `
Home`
+ * - ``
+ *
+ * For checking the raw source code, use `seeInSource()`.
+ *
+ * @param $text
+ * @param null $selector
+ * @see \Codeception\Lib\InnerBrowser::dontSee()
+ */
+ public function dontSee($text, $selector = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSee', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string in its
+ * raw source code.
+ *
+ * ``` php
+ * seeInSource('
Green eggs & ham
');
+ * ```
+ *
+ * @param $raw
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeInSource()
+ */
+ public function canSeeInSource($raw) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string in its
+ * raw source code.
+ *
+ * ``` php
+ * seeInSource('
Green eggs & ham
');
+ * ```
+ *
+ * @param $raw
+ * @see \Codeception\Lib\InnerBrowser::seeInSource()
+ */
+ public function seeInSource($raw) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string in its
+ * raw source code.
+ *
+ * ```php
+ * dontSeeInSource('
Green eggs & ham
');
+ * ```
+ *
+ * @param $raw
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInSource()
+ */
+ public function cantSeeInSource($raw) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current page contains the given string in its
+ * raw source code.
+ *
+ * ```php
+ * dontSeeInSource('
Green eggs & ham
');
+ * ```
+ *
+ * @param $raw
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInSource()
+ */
+ public function dontSeeInSource($raw) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInSource', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there's a link with the specified text.
+ * Give a full URL as the second parameter to match links with that exact URL.
+ *
+ * ``` php
+ * seeLink('Logout'); // matches Logout
+ * $I->seeLink('Logout','/logout'); // matches Logout
+ * ?>
+ * ```
+ *
+ * @param $text
+ * @param null $url
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeLink()
+ */
+ public function canSeeLink($text, $url = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeLink', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there's a link with the specified text.
+ * Give a full URL as the second parameter to match links with that exact URL.
+ *
+ * ``` php
+ * seeLink('Logout'); // matches Logout
+ * $I->seeLink('Logout','/logout'); // matches Logout
+ * ?>
+ * ```
+ *
+ * @param $text
+ * @param null $url
+ * @see \Codeception\Lib\InnerBrowser::seeLink()
+ */
+ public function seeLink($text, $url = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeLink', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page doesn't contain a link with the given string.
+ * If the second parameter is given, only links with a matching "href" attribute will be checked.
+ *
+ * ``` php
+ * dontSeeLink('Logout'); // I suppose user is not logged in
+ * $I->dontSeeLink('Checkout now', '/store/cart.php');
+ * ?>
+ * ```
+ *
+ * @param $text
+ * @param null $url
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeLink()
+ */
+ public function cantSeeLink($text, $url = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeLink', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page doesn't contain a link with the given string.
+ * If the second parameter is given, only links with a matching "href" attribute will be checked.
+ *
+ * ``` php
+ * dontSeeLink('Logout'); // I suppose user is not logged in
+ * $I->dontSeeLink('Checkout now', '/store/cart.php');
+ * ?>
+ * ```
+ *
+ * @param $text
+ * @param null $url
+ * @see \Codeception\Lib\InnerBrowser::dontSeeLink()
+ */
+ public function dontSeeLink($text, $url = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeLink', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that current URI contains the given string.
+ *
+ * ``` php
+ * seeInCurrentUrl('home');
+ * // to match: /users/1
+ * $I->seeInCurrentUrl('/users/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl()
+ */
+ public function canSeeInCurrentUrl($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInCurrentUrl', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that current URI contains the given string.
+ *
+ * ``` php
+ * seeInCurrentUrl('home');
+ * // to match: /users/1
+ * $I->seeInCurrentUrl('/users/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl()
+ */
+ public function seeInCurrentUrl($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInCurrentUrl', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URI doesn't contain the given string.
+ *
+ * ``` php
+ * dontSeeInCurrentUrl('/users/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl()
+ */
+ public function cantSeeInCurrentUrl($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInCurrentUrl', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URI doesn't contain the given string.
+ *
+ * ``` php
+ * dontSeeInCurrentUrl('/users/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl()
+ */
+ public function dontSeeInCurrentUrl($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInCurrentUrl', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL is equal to the given string.
+ * Unlike `seeInCurrentUrl`, this only matches the full URL.
+ *
+ * ``` php
+ * seeCurrentUrlEquals('/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals()
+ */
+ public function canSeeCurrentUrlEquals($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlEquals', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL is equal to the given string.
+ * Unlike `seeInCurrentUrl`, this only matches the full URL.
+ *
+ * ``` php
+ * seeCurrentUrlEquals('/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals()
+ */
+ public function seeCurrentUrlEquals($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlEquals', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL doesn't equal the given string.
+ * Unlike `dontSeeInCurrentUrl`, this only matches the full URL.
+ *
+ * ``` php
+ * dontSeeCurrentUrlEquals('/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals()
+ */
+ public function cantSeeCurrentUrlEquals($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlEquals', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL doesn't equal the given string.
+ * Unlike `dontSeeInCurrentUrl`, this only matches the full URL.
+ *
+ * ``` php
+ * dontSeeCurrentUrlEquals('/');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals()
+ */
+ public function dontSeeCurrentUrlEquals($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlEquals', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL matches the given regular expression.
+ *
+ * ``` php
+ * seeCurrentUrlMatches('~$/users/(\d+)~');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches()
+ */
+ public function canSeeCurrentUrlMatches($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlMatches', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the current URL matches the given regular expression.
+ *
+ * ``` php
+ * seeCurrentUrlMatches('~$/users/(\d+)~');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches()
+ */
+ public function seeCurrentUrlMatches($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlMatches', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that current url doesn't match the given regular expression.
+ *
+ * ``` php
+ * dontSeeCurrentUrlMatches('~$/users/(\d+)~');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches()
+ */
+ public function cantSeeCurrentUrlMatches($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlMatches', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that current url doesn't match the given regular expression.
+ *
+ * ``` php
+ * dontSeeCurrentUrlMatches('~$/users/(\d+)~');
+ * ?>
+ * ```
+ *
+ * @param $uri
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches()
+ */
+ public function dontSeeCurrentUrlMatches($uri) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlMatches', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Executes the given regular expression against the current URI and returns the first match.
+ * If no parameters are provided, the full URI is returned.
+ *
+ * ``` php
+ * grabFromCurrentUrl('~$/user/(\d+)/~');
+ * $uri = $I->grabFromCurrentUrl();
+ * ?>
+ * ```
+ *
+ * @param null $uri
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl()
+ */
+ public function grabFromCurrentUrl($uri = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the specified checkbox is checked.
+ *
+ * ``` php
+ * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms
+ * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form.
+ * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]');
+ * ?>
+ * ```
+ *
+ * @param $checkbox
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked()
+ */
+ public function canSeeCheckboxIsChecked($checkbox) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCheckboxIsChecked', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the specified checkbox is checked.
+ *
+ * ``` php
+ * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms
+ * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form.
+ * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]');
+ * ?>
+ * ```
+ *
+ * @param $checkbox
+ * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked()
+ */
+ public function seeCheckboxIsChecked($checkbox) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCheckboxIsChecked', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Check that the specified checkbox is unchecked.
+ *
+ * ``` php
+ * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms
+ * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form.
+ * ?>
+ * ```
+ *
+ * @param $checkbox
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked()
+ */
+ public function cantSeeCheckboxIsChecked($checkbox) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCheckboxIsChecked', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Check that the specified checkbox is unchecked.
+ *
+ * ``` php
+ * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms
+ * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form.
+ * ?>
+ * ```
+ *
+ * @param $checkbox
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked()
+ */
+ public function dontSeeCheckboxIsChecked($checkbox) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCheckboxIsChecked', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given input field or textarea contains the given value.
+ * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath.
+ *
+ * ``` php
+ * seeInField('Body','Type your comment here');
+ * $I->seeInField('form textarea[name=body]','Type your comment here');
+ * $I->seeInField('form input[type=hidden]','hidden_value');
+ * $I->seeInField('#searchform input','Search');
+ * $I->seeInField('//form/*[@name=search]','Search');
+ * $I->seeInField(['name' => 'search'], 'Search');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $value
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeInField()
+ */
+ public function canSeeInField($field, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInField', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given input field or textarea contains the given value.
+ * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath.
+ *
+ * ``` php
+ * seeInField('Body','Type your comment here');
+ * $I->seeInField('form textarea[name=body]','Type your comment here');
+ * $I->seeInField('form input[type=hidden]','hidden_value');
+ * $I->seeInField('#searchform input','Search');
+ * $I->seeInField('//form/*[@name=search]','Search');
+ * $I->seeInField(['name' => 'search'], 'Search');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $value
+ * @see \Codeception\Lib\InnerBrowser::seeInField()
+ */
+ public function seeInField($field, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInField', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that an input field or textarea doesn't contain the given value.
+ * For fuzzy locators, the field is matched by label text, CSS and XPath.
+ *
+ * ``` php
+ * dontSeeInField('Body','Type your comment here');
+ * $I->dontSeeInField('form textarea[name=body]','Type your comment here');
+ * $I->dontSeeInField('form input[type=hidden]','hidden_value');
+ * $I->dontSeeInField('#searchform input','Search');
+ * $I->dontSeeInField('//form/*[@name=search]','Search');
+ * $I->dontSeeInField(['name' => 'search'], 'Search');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $value
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInField()
+ */
+ public function cantSeeInField($field, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInField', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that an input field or textarea doesn't contain the given value.
+ * For fuzzy locators, the field is matched by label text, CSS and XPath.
+ *
+ * ``` php
+ * dontSeeInField('Body','Type your comment here');
+ * $I->dontSeeInField('form textarea[name=body]','Type your comment here');
+ * $I->dontSeeInField('form input[type=hidden]','hidden_value');
+ * $I->dontSeeInField('#searchform input','Search');
+ * $I->dontSeeInField('//form/*[@name=search]','Search');
+ * $I->dontSeeInField(['name' => 'search'], 'Search');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $value
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInField()
+ */
+ public function dontSeeInField($field, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInField', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks if the array of form parameters (name => value) are set on the form matched with the
+ * passed selector.
+ *
+ * ``` php
+ * seeInFormFields('form[name=myform]', [
+ * 'input1' => 'value',
+ * 'input2' => 'other value',
+ * ]);
+ * ?>
+ * ```
+ *
+ * For multi-select elements, or to check values of multiple elements with the same name, an
+ * array may be passed:
+ *
+ * ``` php
+ * seeInFormFields('.form-class', [
+ * 'multiselect' => [
+ * 'value1',
+ * 'value2',
+ * ],
+ * 'checkbox[]' => [
+ * 'a checked value',
+ * 'another checked value',
+ * ],
+ * ]);
+ * ?>
+ * ```
+ *
+ * Additionally, checkbox values can be checked with a boolean.
+ *
+ * ``` php
+ * seeInFormFields('#form-id', [
+ * 'checkbox1' => true, // passes if checked
+ * 'checkbox2' => false, // passes if unchecked
+ * ]);
+ * ?>
+ * ```
+ *
+ * Pair this with submitForm for quick testing magic.
+ *
+ * ``` php
+ * 'value',
+ * 'field2' => 'another value',
+ * 'checkbox1' => true,
+ * // ...
+ * ];
+ * $I->submitForm('//form[@id=my-form]', $form, 'submitButton');
+ * // $I->amOnPage('/path/to/form-page') may be needed
+ * $I->seeInFormFields('//form[@id=my-form]', $form);
+ * ?>
+ * ```
+ *
+ * @param $formSelector
+ * @param $params
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeInFormFields()
+ */
+ public function canSeeInFormFields($formSelector, $params) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInFormFields', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks if the array of form parameters (name => value) are set on the form matched with the
+ * passed selector.
+ *
+ * ``` php
+ * seeInFormFields('form[name=myform]', [
+ * 'input1' => 'value',
+ * 'input2' => 'other value',
+ * ]);
+ * ?>
+ * ```
+ *
+ * For multi-select elements, or to check values of multiple elements with the same name, an
+ * array may be passed:
+ *
+ * ``` php
+ * seeInFormFields('.form-class', [
+ * 'multiselect' => [
+ * 'value1',
+ * 'value2',
+ * ],
+ * 'checkbox[]' => [
+ * 'a checked value',
+ * 'another checked value',
+ * ],
+ * ]);
+ * ?>
+ * ```
+ *
+ * Additionally, checkbox values can be checked with a boolean.
+ *
+ * ``` php
+ * seeInFormFields('#form-id', [
+ * 'checkbox1' => true, // passes if checked
+ * 'checkbox2' => false, // passes if unchecked
+ * ]);
+ * ?>
+ * ```
+ *
+ * Pair this with submitForm for quick testing magic.
+ *
+ * ``` php
+ * 'value',
+ * 'field2' => 'another value',
+ * 'checkbox1' => true,
+ * // ...
+ * ];
+ * $I->submitForm('//form[@id=my-form]', $form, 'submitButton');
+ * // $I->amOnPage('/path/to/form-page') may be needed
+ * $I->seeInFormFields('//form[@id=my-form]', $form);
+ * ?>
+ * ```
+ *
+ * @param $formSelector
+ * @param $params
+ * @see \Codeception\Lib\InnerBrowser::seeInFormFields()
+ */
+ public function seeInFormFields($formSelector, $params) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInFormFields', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks if the array of form parameters (name => value) are not set on the form matched with
+ * the passed selector.
+ *
+ * ``` php
+ * dontSeeInFormFields('form[name=myform]', [
+ * 'input1' => 'non-existent value',
+ * 'input2' => 'other non-existent value',
+ * ]);
+ * ?>
+ * ```
+ *
+ * To check that an element hasn't been assigned any one of many values, an array can be passed
+ * as the value:
+ *
+ * ``` php
+ * dontSeeInFormFields('.form-class', [
+ * 'fieldName' => [
+ * 'This value shouldn\'t be set',
+ * 'And this value shouldn\'t be set',
+ * ],
+ * ]);
+ * ?>
+ * ```
+ *
+ * Additionally, checkbox values can be checked with a boolean.
+ *
+ * ``` php
+ * dontSeeInFormFields('#form-id', [
+ * 'checkbox1' => true, // fails if checked
+ * 'checkbox2' => false, // fails if unchecked
+ * ]);
+ * ?>
+ * ```
+ *
+ * @param $formSelector
+ * @param $params
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInFormFields()
+ */
+ public function cantSeeInFormFields($formSelector, $params) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInFormFields', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks if the array of form parameters (name => value) are not set on the form matched with
+ * the passed selector.
+ *
+ * ``` php
+ * dontSeeInFormFields('form[name=myform]', [
+ * 'input1' => 'non-existent value',
+ * 'input2' => 'other non-existent value',
+ * ]);
+ * ?>
+ * ```
+ *
+ * To check that an element hasn't been assigned any one of many values, an array can be passed
+ * as the value:
+ *
+ * ``` php
+ * dontSeeInFormFields('.form-class', [
+ * 'fieldName' => [
+ * 'This value shouldn\'t be set',
+ * 'And this value shouldn\'t be set',
+ * ],
+ * ]);
+ * ?>
+ * ```
+ *
+ * Additionally, checkbox values can be checked with a boolean.
+ *
+ * ``` php
+ * dontSeeInFormFields('#form-id', [
+ * 'checkbox1' => true, // fails if checked
+ * 'checkbox2' => false, // fails if unchecked
+ * ]);
+ * ?>
+ * ```
+ *
+ * @param $formSelector
+ * @param $params
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInFormFields()
+ */
+ public function dontSeeInFormFields($formSelector, $params) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInFormFields', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Submits the given form on the page, optionally with the given form
+ * values. Give the form fields values as an array.
+ *
+ * Although this function can be used as a short-hand version of
+ * `fillField()`, `selectOption()`, `click()` etc. it has some important
+ * differences:
+ *
+ * * Only field *names* may be used, not CSS/XPath selectors nor field labels
+ * * If a field is sent to this function that does *not* exist on the page,
+ * it will silently be added to the HTTP request. This is helpful for testing
+ * some types of forms, but be aware that you will *not* get an exception
+ * like you would if you called `fillField()` or `selectOption()` with
+ * a missing field.
+ *
+ * Fields that are not provided will be filled by their values from the page,
+ * or from any previous calls to `fillField()`, `selectOption()` etc.
+ * You don't need to click the 'Submit' button afterwards.
+ * This command itself triggers the request to form's action.
+ *
+ * You can optionally specify which button's value to include
+ * in the request with the last parameter (as an alternative to
+ * explicitly setting its value in the second parameter), as
+ * button values are not otherwise included in the request.
+ *
+ * Examples:
+ *
+ * ``` php
+ * submitForm('#login', [
+ * 'login' => 'davert',
+ * 'password' => '123456'
+ * ]);
+ * // or
+ * $I->submitForm('#login', [
+ * 'login' => 'davert',
+ * 'password' => '123456'
+ * ], 'submitButtonName');
+ *
+ * ```
+ *
+ * For example, given this sample "Sign Up" form:
+ *
+ * ``` html
+ *
+ * ```
+ *
+ * You could write the following to submit it:
+ *
+ * ``` php
+ * submitForm(
+ * '#userForm',
+ * [
+ * 'user' => [
+ * 'login' => 'Davert',
+ * 'password' => '123456',
+ * 'agree' => true
+ * ]
+ * ],
+ * 'submitButton'
+ * );
+ * ```
+ * Note that "2" will be the submitted value for the "plan" field, as it is
+ * the selected option.
+ *
+ * You can also emulate a JavaScript submission by not specifying any
+ * buttons in the third parameter to submitForm.
+ *
+ * ```php
+ * submitForm(
+ * '#userForm',
+ * [
+ * 'user' => [
+ * 'login' => 'Davert',
+ * 'password' => '123456',
+ * 'agree' => true
+ * ]
+ * ]
+ * );
+ * ```
+ *
+ * This function works well when paired with `seeInFormFields()`
+ * for quickly testing CRUD interfaces and form validation logic.
+ *
+ * ``` php
+ * 'value',
+ * 'field2' => 'another value',
+ * 'checkbox1' => true,
+ * // ...
+ * ];
+ * $I->submitForm('#my-form', $form, 'submitButton');
+ * // $I->amOnPage('/path/to/form-page') may be needed
+ * $I->seeInFormFields('#my-form', $form);
+ * ```
+ *
+ * Parameter values can be set to arrays for multiple input fields
+ * of the same name, or multi-select combo boxes. For checkboxes,
+ * you can use either the string value or boolean `true`/`false` which will
+ * be replaced by the checkbox's value in the DOM.
+ *
+ * ``` php
+ * submitForm('#my-form', [
+ * 'field1' => 'value',
+ * 'checkbox' => [
+ * 'value of first checkbox',
+ * 'value of second checkbox',
+ * ],
+ * 'otherCheckboxes' => [
+ * true,
+ * false,
+ * false
+ * ],
+ * 'multiselect' => [
+ * 'first option value',
+ * 'second option value'
+ * ]
+ * ]);
+ * ```
+ *
+ * Mixing string and boolean values for a checkbox's value is not supported
+ * and may produce unexpected results.
+ *
+ * Field names ending in `[]` must be passed without the trailing square
+ * bracket characters, and must contain an array for its value. This allows
+ * submitting multiple values with the same name, consider:
+ *
+ * ```php
+ * submitForm('#my-form', [
+ * 'field[]' => 'value',
+ * 'field[]' => 'another value', // 'field[]' is already a defined key
+ * ]);
+ * ```
+ *
+ * The solution is to pass an array value:
+ *
+ * ```php
+ * submitForm('#my-form', [
+ * 'field' => [
+ * 'value',
+ * 'another value',
+ * ]
+ * ]);
+ * ```
+ *
+ * @param $selector
+ * @param $params
+ * @param $button
+ * @see \Codeception\Lib\InnerBrowser::submitForm()
+ */
+ public function submitForm($selector, $params, $button = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('submitForm', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Fills a text field or textarea with the given string.
+ *
+ * ``` php
+ * fillField("//input[@type='text']", "Hello World!");
+ * $I->fillField(['name' => 'email'], 'jon@mail.com');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $value
+ * @see \Codeception\Lib\InnerBrowser::fillField()
+ */
+ public function fillField($field, $value) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('fillField', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Selects an option in a select tag or in radio button group.
+ *
+ * ``` php
+ * selectOption('form select[name=account]', 'Premium');
+ * $I->selectOption('form input[name=payment]', 'Monthly');
+ * $I->selectOption('//form/select[@name=account]', 'Monthly');
+ * ?>
+ * ```
+ *
+ * Provide an array for the second argument to select multiple options:
+ *
+ * ``` php
+ * selectOption('Which OS do you use?', array('Windows','Linux'));
+ * ?>
+ * ```
+ *
+ * @param $select
+ * @param $option
+ * @see \Codeception\Lib\InnerBrowser::selectOption()
+ */
+ public function selectOption($select, $option) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('selectOption', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Ticks a checkbox. For radio buttons, use the `selectOption` method instead.
+ *
+ * ``` php
+ * checkOption('#agree');
+ * ?>
+ * ```
+ *
+ * @param $option
+ * @see \Codeception\Lib\InnerBrowser::checkOption()
+ */
+ public function checkOption($option) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('checkOption', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Unticks a checkbox.
+ *
+ * ``` php
+ * uncheckOption('#notify');
+ * ?>
+ * ```
+ *
+ * @param $option
+ * @see \Codeception\Lib\InnerBrowser::uncheckOption()
+ */
+ public function uncheckOption($option) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('uncheckOption', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Attaches a file relative to the Codeception data directory to the given file upload field.
+ *
+ * ``` php
+ * attachFile('input[@type="file"]', 'prices.xls');
+ * ?>
+ * ```
+ *
+ * @param $field
+ * @param $filename
+ * @see \Codeception\Lib\InnerBrowser::attachFile()
+ */
+ public function attachFile($field, $filename) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('attachFile', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * If your page triggers an ajax request, you can perform it manually.
+ * This action sends a GET ajax request with specified params.
+ *
+ * See ->sendAjaxPostRequest for examples.
+ *
+ * @param $uri
+ * @param $params
+ * @see \Codeception\Lib\InnerBrowser::sendAjaxGetRequest()
+ */
+ public function sendAjaxGetRequest($uri, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxGetRequest', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * If your page triggers an ajax request, you can perform it manually.
+ * This action sends a POST ajax request with specified params.
+ * Additional params can be passed as array.
+ *
+ * Example:
+ *
+ * Imagine that by clicking checkbox you trigger ajax request which updates user settings.
+ * We emulate that click by running this ajax request manually.
+ *
+ * ``` php
+ * sendAjaxPostRequest('/updateSettings', array('notifications' => true)); // POST
+ * $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GET
+ *
+ * ```
+ *
+ * @param $uri
+ * @param $params
+ * @see \Codeception\Lib\InnerBrowser::sendAjaxPostRequest()
+ */
+ public function sendAjaxPostRequest($uri, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxPostRequest', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * If your page triggers an ajax request, you can perform it manually.
+ * This action sends an ajax request with specified method and params.
+ *
+ * Example:
+ *
+ * You need to perform an ajax request specifying the HTTP method.
+ *
+ * ``` php
+ * sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title'));
+ *
+ * ```
+ *
+ * @param $method
+ * @param $uri
+ * @param $params
+ * @see \Codeception\Lib\InnerBrowser::sendAjaxRequest()
+ */
+ public function sendAjaxRequest($method, $uri, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('sendAjaxRequest', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Finds and returns the text contents of the given element.
+ * If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression.
+ *
+ * ``` php
+ * grabTextFrom('h1');
+ * $heading = $I->grabTextFrom('descendant-or-self::h1');
+ * $value = $I->grabTextFrom('~
+ * ```
+ *
+ * @param $cssOrXPathOrRegex
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::grabTextFrom()
+ */
+ public function grabTextFrom($cssOrXPathOrRegex) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Grabs the value of the given attribute value from the given element.
+ * Fails if element is not found.
+ *
+ * ``` php
+ * grabAttributeFrom('#tooltip', 'title');
+ * ?>
+ * ```
+ *
+ *
+ * @param $cssOrXpath
+ * @param $attribute
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom()
+ */
+ public function grabAttributeFrom($cssOrXpath, $attribute) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Grabs either the text content, or attribute values, of nodes
+ * matched by $cssOrXpath and returns them as an array.
+ *
+ * ```html
+ * First
+ * Second
+ * Third
+ * ```
+ *
+ * ```php
+ * grabMultiple('a');
+ *
+ * // would return ['#first', '#second', '#third']
+ * $aLinks = $I->grabMultiple('a', 'href');
+ * ?>
+ * ```
+ *
+ * @param $cssOrXpath
+ * @param $attribute
+ * @return string[]
+ * @see \Codeception\Lib\InnerBrowser::grabMultiple()
+ */
+ public function grabMultiple($cssOrXpath, $attribute = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabMultiple', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * @param $field
+ *
+ * @return array|mixed|null|string
+ * @see \Codeception\Lib\InnerBrowser::grabValueFrom()
+ */
+ public function grabValueFrom($field) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Sets a cookie with the given name and value.
+ * You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument.
+ *
+ * ``` php
+ * setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3');
+ * ?>
+ * ```
+ *
+ * @param $name
+ * @param $val
+ * @param array $params
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::setCookie()
+ */
+ public function setCookie($name, $val, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('setCookie', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Grabs a cookie value.
+ * You can set additional cookie params like `domain`, `path` in array passed as last argument.
+ *
+ * @param $cookie
+ *
+ * @param array $params
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::grabCookie()
+ */
+ public function grabCookie($cookie, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that a cookie with the given name is set.
+ * You can set additional cookie params like `domain`, `path` as array passed in last argument.
+ *
+ * ``` php
+ * seeCookie('PHPSESSID');
+ * ?>
+ * ```
+ *
+ * @param $cookie
+ * @param array $params
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeCookie()
+ */
+ public function canSeeCookie($cookie, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCookie', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that a cookie with the given name is set.
+ * You can set additional cookie params like `domain`, `path` as array passed in last argument.
+ *
+ * ``` php
+ * seeCookie('PHPSESSID');
+ * ?>
+ * ```
+ *
+ * @param $cookie
+ * @param array $params
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::seeCookie()
+ */
+ public function seeCookie($cookie, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there isn't a cookie with the given name.
+ * You can set additional cookie params like `domain`, `path` as array passed in last argument.
+ *
+ * @param $cookie
+ *
+ * @param array $params
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCookie()
+ */
+ public function cantSeeCookie($cookie, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCookie', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there isn't a cookie with the given name.
+ * You can set additional cookie params like `domain`, `path` as array passed in last argument.
+ *
+ * @param $cookie
+ *
+ * @param array $params
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::dontSeeCookie()
+ */
+ public function dontSeeCookie($cookie, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCookie', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Unsets cookie with the given name.
+ * You can set additional cookie params like `domain`, `path` in array passed as last argument.
+ *
+ * @param $cookie
+ *
+ * @param array $params
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::resetCookie()
+ */
+ public function resetCookie($name, $params = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Action('resetCookie', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given element exists on the page and is visible.
+ * You can also specify expected attributes of this element.
+ *
+ * ``` php
+ * seeElement('.error');
+ * $I->seeElement('//form/input[1]');
+ * $I->seeElement('input', ['name' => 'login']);
+ * $I->seeElement('input', ['value' => '123456']);
+ *
+ * // strict locator in first arg, attributes in second
+ * $I->seeElement(['css' => 'form input'], ['name' => 'login']);
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param array $attributes
+ * @return
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeElement()
+ */
+ public function canSeeElement($selector, $attributes = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElement', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given element exists on the page and is visible.
+ * You can also specify expected attributes of this element.
+ *
+ * ``` php
+ * seeElement('.error');
+ * $I->seeElement('//form/input[1]');
+ * $I->seeElement('input', ['name' => 'login']);
+ * $I->seeElement('input', ['value' => '123456']);
+ *
+ * // strict locator in first arg, attributes in second
+ * $I->seeElement(['css' => 'form input'], ['name' => 'login']);
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param array $attributes
+ * @return
+ * @see \Codeception\Lib\InnerBrowser::seeElement()
+ */
+ public function seeElement($selector, $attributes = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElement', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given element is invisible or not present on the page.
+ * You can also specify expected attributes of this element.
+ *
+ * ``` php
+ * dontSeeElement('.error');
+ * $I->dontSeeElement('//form/input[1]');
+ * $I->dontSeeElement('input', ['name' => 'login']);
+ * $I->dontSeeElement('input', ['value' => '123456']);
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param array $attributes
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeElement()
+ */
+ public function cantSeeElement($selector, $attributes = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElement', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given element is invisible or not present on the page.
+ * You can also specify expected attributes of this element.
+ *
+ * ``` php
+ * dontSeeElement('.error');
+ * $I->dontSeeElement('//form/input[1]');
+ * $I->dontSeeElement('input', ['name' => 'login']);
+ * $I->dontSeeElement('input', ['value' => '123456']);
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param array $attributes
+ * @see \Codeception\Lib\InnerBrowser::dontSeeElement()
+ */
+ public function dontSeeElement($selector, $attributes = null) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeElement', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there are a certain number of elements matched by the given locator on the page.
+ *
+ * ``` php
+ * seeNumberOfElements('tr', 10);
+ * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements
+ * ?>
+ * ```
+ * @param $selector
+ * @param mixed $expected :
+ * - string: strict number
+ * - array: range of numbers [0,10]
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements()
+ */
+ public function canSeeNumberOfElements($selector, $expected) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElements', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that there are a certain number of elements matched by the given locator on the page.
+ *
+ * ``` php
+ * seeNumberOfElements('tr', 10);
+ * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements
+ * ?>
+ * ```
+ * @param $selector
+ * @param mixed $expected :
+ * - string: strict number
+ * - array: range of numbers [0,10]
+ * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements()
+ */
+ public function seeNumberOfElements($selector, $expected) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElements', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given option is selected.
+ *
+ * ``` php
+ * seeOptionIsSelected('#form input[name=payment]', 'Visa');
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param $optionText
+ *
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected()
+ */
+ public function canSeeOptionIsSelected($selector, $optionText) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionIsSelected', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given option is selected.
+ *
+ * ``` php
+ * seeOptionIsSelected('#form input[name=payment]', 'Visa');
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param $optionText
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected()
+ */
+ public function seeOptionIsSelected($selector, $optionText) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionIsSelected', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given option is not selected.
+ *
+ * ``` php
+ * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa');
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param $optionText
+ *
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected()
+ */
+ public function cantSeeOptionIsSelected($selector, $optionText) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionIsSelected', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the given option is not selected.
+ *
+ * ``` php
+ * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa');
+ * ?>
+ * ```
+ *
+ * @param $selector
+ * @param $optionText
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected()
+ */
+ public function dontSeeOptionIsSelected($selector, $optionText) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeOptionIsSelected', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Asserts that current page has 404 response status code.
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seePageNotFound()
+ */
+ public function canSeePageNotFound() {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seePageNotFound', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Asserts that current page has 404 response status code.
+ * @see \Codeception\Lib\InnerBrowser::seePageNotFound()
+ */
+ public function seePageNotFound() {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seePageNotFound', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that response code is equal to value provided.
+ *
+ * @param $code
+ *
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs()
+ */
+ public function canSeeResponseCodeIs($code) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeResponseCodeIs', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that response code is equal to value provided.
+ *
+ * @param $code
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs()
+ */
+ public function seeResponseCodeIs($code) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeResponseCodeIs', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page title contains the given string.
+ *
+ * ``` php
+ * seeInTitle('Blog - Post #1');
+ * ?>
+ * ```
+ *
+ * @param $title
+ *
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::seeInTitle()
+ */
+ public function canSeeInTitle($title) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInTitle', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page title contains the given string.
+ *
+ * ``` php
+ * seeInTitle('Blog - Post #1');
+ * ?>
+ * ```
+ *
+ * @param $title
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::seeInTitle()
+ */
+ public function seeInTitle($title) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInTitle', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page title does not contain the given string.
+ *
+ * @param $title
+ *
+ * @return mixed
+ * Conditional Assertion: Test won't be stopped on fail
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle()
+ */
+ public function cantSeeInTitle($title) {
+ return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInTitle', func_get_args()));
+ }
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Checks that the page title does not contain the given string.
+ *
+ * @param $title
+ *
+ * @return mixed
+ * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle()
+ */
+ public function dontSeeInTitle($title) {
+ return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInTitle', func_get_args()));
+ }
+
+
+ /**
+ * [!] Method is generated. Documentation taken from corresponding module.
+ *
+ * Switch to iframe or frame on the page.
+ *
+ * Example:
+ * ``` html
+ *