From 460264d3897a7da9abceec6fb99d599a779c06eb Mon Sep 17 00:00:00 2001
From: kenjis
Date: Sun, 26 Jun 2016 01:21:35 +0900
Subject: [PATCH 0001/1807] Update travis-ci link
Signed-off-by: Kenji Suzuki
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index d8499227158d..e5d1348b01aa 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# CodeIgniter 4 Development
-[![Build Status](https://travis-ci.org/lonnieezell/CodeIgniter4.svg?branch=develop)](https://travis-ci.org/lonnieezell/CodeIgniter4)
+[![Build Status](https://travis-ci.org/bcit-ci/CodeIgniter4.svg?branch=develop)](https://travis-ci.org/bcit-ci/CodeIgniter4)
[![StyleCI](https://styleci.io/repos/41463886/shield)](https://styleci.io/repos/41463886)
From 1dd277a95533e3ed7a16b87c625cb3ee61a2ad73 Mon Sep 17 00:00:00 2001
From: "Instructor, Computer Systems Technology"
Date: Sat, 25 Jun 2016 12:58:05 -0700
Subject: [PATCH 0002/1807] Update README.md
Add a note about index.php, since this seems to be causing no end of confusion on the forum!
---
README.md | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/README.md b/README.md
index e5d1348b01aa..7aac60f31d89 100644
--- a/README.md
+++ b/README.md
@@ -16,6 +16,15 @@ while still keeping as many of the things intact that has made people love the f
More information about the plans for version 4 can be found in [the announcement](http://forum.codeigniter.com/thread-62615.html) on the forums.
+## Important Change with index.php
+
+index.php is no longer in the root of the project! It has been moved inside the *public* folder,
+for better security and separation of components.
+
+This means that you should configure your web server to "point" to your project's *public* folder, and
+not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the
+framework are exposed.
+
## Repository Management
We use Github issues to track **BUGS** and to track approved **DEVELOPMENT** work packages.
We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss
From fc44ee6523c71c65d3defea80487a378a738ffa0 Mon Sep 17 00:00:00 2001
From: "Instructor, Computer Systems Technology"
Date: Sat, 25 Jun 2016 12:59:42 -0700
Subject: [PATCH 0003/1807] Update README.md
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index 7aac60f31d89..a9c0c0e75d17 100644
--- a/README.md
+++ b/README.md
@@ -25,6 +25,9 @@ This means that you should configure your web server to "point" to your project'
not to the project root. A better practice would be to configure a virtual host to point there. A poor practice would be to point your web server to the project root and expect to enter *public/...*, as the rest of your logic and the
framework are exposed.
+**Please** read the user guide for a better explanation of how CI4 works!
+The user guide updating and deployment is a bit awkward at the moment, but we are working on it!
+
## Repository Management
We use Github issues to track **BUGS** and to track approved **DEVELOPMENT** work packages.
We use our [forum](http://forum.codeigniter.com) to provide SUPPORT and to discuss
From 8296832a3847e2c00ea015da5633d7aff7276062 Mon Sep 17 00:00:00 2001
From: "Instructor, Computer Systems Technology"
Date: Sat, 25 Jun 2016 14:49:04 -0700
Subject: [PATCH 0004/1807] Create index.html
Provide a helpful message for those trying to "run" the project "out of the box".
---
index.html | 15 +++++++++++++++
1 file changed, 15 insertions(+)
create mode 100644 index.html
diff --git a/index.html b/index.html
new file mode 100644
index 000000000000..7e7cda4bbf72
--- /dev/null
+++ b/index.html
@@ -0,0 +1,15 @@
+
+
+
+ CodeIgniter 4 ... almost!
+
+
+
+
+ If you see this message, you have not configured your web server properly.
+ You need to set your "document root" to the public
folder
+ inside your project. This could be your default setting, or that of
+ a virtual host, depending on how you set up your local development
+ environment.
+
+
From 1341152691fd408995bfaffa9043bd1787cfae62 Mon Sep 17 00:00:00 2001
From: Master Yoda
Date: Sat, 25 Jun 2016 23:51:19 -0700
Subject: [PATCH 0005/1807] gh-pages mods to user guide makefile
Signed-off-by:Master Yoda
---
user_guide_src/Makefile | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/user_guide_src/Makefile b/user_guide_src/Makefile
index 519e1136ff54..425a2ef113a5 100644
--- a/user_guide_src/Makefile
+++ b/user_guide_src/Makefile
@@ -6,13 +6,14 @@ SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = build
+GHBUILDDIR = ../../CodeIgniter4-guide
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest ghpages
help:
@echo "Please use \`make ' where is one of"
@@ -128,3 +129,9 @@ doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
+
+ghpages:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(GHBUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(GHBUILDDIR)/html."
+
From e6f1519df10f21299da5160b1d8b573de8a78664 Mon Sep 17 00:00:00 2001
From: kenjis
Date: Sun, 26 Jun 2016 16:59:56 +0900
Subject: [PATCH 0006/1807] Fix white spaces
Signed-off-by: Kenji Suzuki
---
system/Commands/MigrationsCommand.php | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/system/Commands/MigrationsCommand.php b/system/Commands/MigrationsCommand.php
index 49a0d8db5f3d..ed4e76ae0992 100644
--- a/system/Commands/MigrationsCommand.php
+++ b/system/Commands/MigrationsCommand.php
@@ -62,7 +62,7 @@ class MigrationsCommand extends \CodeIgniter\Controller
*/
public function __construct()
{
- $this->runner = Services::migrations();
+ $this->runner = Services::migrations();
}
//--------------------------------------------------------------------
@@ -73,12 +73,12 @@ public function __construct()
public function index()
{
CLI::write('Migration Commands', 'white');
- CLI::write(CLI::color('latest', 'yellow'). "\t\tMigrates database to latest available migration.");
- CLI::write(CLI::color('current', 'yellow'). "\t\tMigrates database to version set as 'current' in configuration.");
- CLI::write(CLI::color('version [v]', 'yellow'). "\tMigrates database to version {v}.");
- CLI::write(CLI::color('rollback', 'yellow'). "\tRuns all migrations 'down' to version 0.");
- CLI::write(CLI::color('refresh', 'yellow'). "\t\tUninstalls and re-runs all migrations to freshen database.");
- CLI::write(CLI::color('seed [name]', 'yellow'). "\tRuns the seeder named [name].");
+ CLI::write(CLI::color('latest', 'yellow'). "\t\tMigrates database to latest available migration.");
+ CLI::write(CLI::color('current', 'yellow'). "\t\tMigrates database to version set as 'current' in configuration.");
+ CLI::write(CLI::color('version [v]', 'yellow'). "\tMigrates database to version {v}.");
+ CLI::write(CLI::color('rollback', 'yellow'). "\tRuns all migrations 'down' to version 0.");
+ CLI::write(CLI::color('refresh', 'yellow'). "\t\tUninstalls and re-runs all migrations to freshen database.");
+ CLI::write(CLI::color('seed [name]', 'yellow'). "\tRuns the seeder named [name].");
}
//--------------------------------------------------------------------
From 6f6290c129141c6a87cd254c3e04a98f956a212d Mon Sep 17 00:00:00 2001
From: "Instructor, Computer Systems Technology"
Date: Sun, 26 Jun 2016 11:06:30 -0700
Subject: [PATCH 0007/1807] Update welcome_message.php
Fixed incorrect user guide link!
---
application/Views/welcome_message.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/application/Views/welcome_message.php b/application/Views/welcome_message.php
index 1aaaec2d1b69..1d566b41473a 100644
--- a/application/Views/welcome_message.php
+++ b/application/Views/welcome_message.php
@@ -125,7 +125,7 @@
If you are exploring CodeIgniter for the very first time, you
should start by reading the (in progress)
- User Guide.
+ User Guide.
From 07d27ab57f30a670a003fa0525926084df46a01a Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Sun, 26 Jun 2016 14:00:55 -0500
Subject: [PATCH 0008/1807] Removing StyleCI badge.
---
README.md | 1 -
1 file changed, 1 deletion(-)
diff --git a/README.md b/README.md
index a9c0c0e75d17..c59b1ea652b9 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,6 @@
[![Build Status](https://travis-ci.org/bcit-ci/CodeIgniter4.svg?branch=develop)](https://travis-ci.org/bcit-ci/CodeIgniter4)
-[![StyleCI](https://styleci.io/repos/41463886/shield)](https://styleci.io/repos/41463886)
## What is CodeIgniter?
CodeIgniter is a PHP full-stack web framework that is light, fast, flexible, and secure.
From 4735011481ba62f46afe891f174ebea74c48e0ff Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Sun, 26 Jun 2016 22:12:48 -0500
Subject: [PATCH 0009/1807] Adding :hash placeholder for routes. Fixes #130
---
system/Router/RouteCollection.php | 1 +
user_guide_src/source/general/routing.rst | 4 +++-
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php
index c4988523673b..ab56b3f2994e 100644
--- a/system/Router/RouteCollection.php
+++ b/system/Router/RouteCollection.php
@@ -120,6 +120,7 @@ class RouteCollection implements RouteCollectionInterface
'num' => '[0-9]+',
'alpha' => '[a-zA-Z]+',
'alphanum' => '[a-zA-Z0-9]+',
+ 'hash' => '[^/]+',
];
/**
diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst
index 28eac82202d7..d1ebabe8164c 100644
--- a/user_guide_src/source/general/routing.rst
+++ b/user_guide_src/source/general/routing.rst
@@ -62,7 +62,9 @@ The following placeholders are available for you to use in your routes:
* **(:segment)** will match any character except for a forward slash (/) restricting the result to a single segment.
* **(:num)** will match any integer.
* **(:alpha)** will match any string of alphabetic characters
-* **(alphanum)** will match any string of alphabetic characters or integers, or any combination of the two.
+* **(:alphanum)** will match any string of alphabetic characters or integers, or any combination of the two.
+* **(:hash)** is the same as **:segment**, but can be used to easily see which routes use hashed ids (see the
+:doc:`Model ` docs.
Examples
========
From ba54dc0932b409015b9c5f2ddd26fb51812e0659 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 00:54:04 -0500
Subject: [PATCH 0010/1807] Initial work on porting the cache library over.
---
application/Config/Cache.php | 84 +++++
application/Config/Services.php | 27 +-
system/Cache/CacheFactory.php | 62 ++++
system/Cache/CacheInterface.php | 108 ++++++
system/Cache/Handlers/DummyHandler.php | 135 +++++++
system/Cache/Handlers/FileHandler.php | 474 +++++++++++++++++++++++++
system/Common.php | 2 +-
7 files changed, 888 insertions(+), 4 deletions(-)
create mode 100644 application/Config/Cache.php
create mode 100644 system/Cache/CacheFactory.php
create mode 100644 system/Cache/CacheInterface.php
create mode 100644 system/Cache/Handlers/DummyHandler.php
create mode 100644 system/Cache/Handlers/FileHandler.php
diff --git a/application/Config/Cache.php b/application/Config/Cache.php
new file mode 100644
index 000000000000..582c5be77d91
--- /dev/null
+++ b/application/Config/Cache.php
@@ -0,0 +1,84 @@
+ \CodeIgniter\Cache\Handlers\DummyHandler::class,
+// 'file' => \CodeIgniter\Cache\Handlers\FileHandler::class,
+// 'memcached' => \CodeIgniter\Cache\Handlers\MemcachedHandler::class,
+// 'redis' => \CodeIgniter\Cache\Handlers\RedisHandler::class,
+// 'wincache' => \CodeIgniter\Cache\Handlers\WincacheHandler::class,
+ ];
+}
diff --git a/application/Config/Services.php b/application/Config/Services.php
index 9df755ef2b0e..65df1940c124 100644
--- a/application/Config/Services.php
+++ b/application/Config/Services.php
@@ -49,6 +49,27 @@ public static function autoloader($getShared = true)
//--------------------------------------------------------------------
+ /**
+ * The cache class provides a simple way to store and retrieve
+ * complex data for later.
+ */
+ public static function cache(\Config\Cache $config = null, $getShared = true)
+ {
+ if ($getShared)
+ {
+ return self::getSharedInstance('cache', $config);
+ }
+
+ if (! is_object($config))
+ {
+ $config = new \Config\Cache();
+ }
+
+ return \CodeIgniter\Cache\CacheFactory::getHandler($config);
+ }
+
+ //--------------------------------------------------------------------
+
/**
* The CLI Request class provides for ways to interact with
* a command line request.
@@ -189,10 +210,10 @@ public static function migrations(BaseConfig $config = null, ConnectionInterface
return new MigrationRunner($config, $db);
}
-
+
//--------------------------------------------------------------------
-
-
+
+
/**
* The Negotiate class provides the content negotiation features for
* working the request to determine correct language, encoding, charset,
diff --git a/system/Cache/CacheFactory.php b/system/Cache/CacheFactory.php
new file mode 100644
index 000000000000..41b4d2ee1297
--- /dev/null
+++ b/system/Cache/CacheFactory.php
@@ -0,0 +1,62 @@
+validHandlers) || ! is_array($config->validHandlers))
+ {
+ throw new \InvalidArgumentException('Cache config must have an array of $validHandlers.');
+ }
+
+ if (! isset($config->handler) || ! isset($config->backupHandler))
+ {
+ throw new \InvalidArgumentException('Cache config must have a handler and backupHanlder set.');
+ }
+
+ $handler = ! empty($handler) ? $handler : $config->handler;
+ $backup = ! empty($backup) ? $backup : $config->backupHandler;
+
+ if (! in_array($handler, $config->validHandlers) || ! in_array($backup, $config->validHandlers))
+ {
+ throw new \InvalidArgumentException('Cache config has an invalid handler or backup handler specified.');
+ }
+
+ // Get an instance of our handler.
+ $adapter = new $config->validHandlers[$handler]($config);
+
+ if (! $adapter->isSupported())
+ {
+ $adapter = new $config->validHandlers[$backup]($config);
+
+ if (! $adapter->isSupported())
+ {
+ // Log stuff here, don't throw exception. No need to raise a fuss.
+
+ // Fall back to the dummy adapter.
+ $adapter = new $config->validHandler['dummy']();
+ }
+ }
+
+ return $adapter;
+ }
+
+ //--------------------------------------------------------------------
+
+}
\ No newline at end of file
diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php
new file mode 100644
index 000000000000..35ae33f270fd
--- /dev/null
+++ b/system/Cache/CacheInterface.php
@@ -0,0 +1,108 @@
+prefix = $config->prefix ?: '';
+ $this->path = ! empty($config->path)
+ ? $config->path
+ : WRITEPATH.'cache';
+
+ $this->path = rtrim($this->path, '/').'/';
+ }
+
+ //--------------------------------------------------------------------
+
+
+ /**
+ * Attempts to fetch an item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function get(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $data = $this->getItem($key);
+
+ return is_array($data) ? $data['data'] : null;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Saves an item to the cache store.
+ *
+ * The $raw parameter is only utilized by Mamcache in order to
+ * allow usage of increment() and decrement().
+ *
+ * @param string $key Cache item name
+ * @param $value the data to save
+ * @param null $ttl Time To Live, in seconds (default 60)
+ * @param bool $raw Whether to store the raw value.
+ *
+ * @return mixed
+ */
+ public function save(string $key, $value, $ttl = null, $raw = false)
+ {
+ $key = $this->prefix.$key;
+
+ $contents = [
+ 'time' => time(),
+ 'ttl' => $ttl,
+ 'data' => $value,
+ ];
+
+ if ($this->writeFile($this->path.$key, serialize($contents)))
+ {
+ chmod($this->path.$key, 0640);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Deletes a specific item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function delete(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ return file_exists($this->path.$key)
+ ? unlink($this->path.$key)
+ : false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic incrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function increment(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ $data = $this->getItem($key);
+
+ if ($data === false)
+ {
+ $data = ['data' => 0, 'ttl' => 60];
+ }
+ elseif (! is_int($data['data']))
+ {
+ return false;
+ }
+
+ $new_value = $data['data']+$offset;
+
+ return $this->save($key, $new_value, $data['ttl'])
+ ? $new_value
+ : false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic decrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function decrement(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ $data = $this->getItem($key);
+
+ if ($data === false)
+ {
+ $data = ['data' => 0, 'ttl' => 60];
+ }
+ elseif (! is_int($data['data']))
+ {
+ return false;
+ }
+
+ $new_value = $data['data']-$offset;
+
+ return $this->save($key, $new_value, $data['ttl'])
+ ? $new_value
+ : false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Will delete all items in the entire cache.
+ *
+ * @return mixed
+ */
+ public function clean()
+ {
+ return $this->deleteFiles($this->path, false, true);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns information on the entire cache.
+ *
+ * The information returned and the structure of the data
+ * varies depending on the handler.
+ *
+ * @return mixed
+ */
+ public function getCacheInfo()
+ {
+ return $this->getDirFileInfo($this->path);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns detailed information about the specific item in the cache.
+ *
+ * @param string $key Cache item name.
+ *
+ * @return mixed
+ */
+ public function getMetaData(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ if ( ! file_exists($this->path.$key))
+ {
+ return FALSE;
+ }
+
+ $data = unserialize(file_get_contents($this->path.$key));
+
+ if (is_array($data))
+ {
+ $mtime = filemtime($this->path.$key);
+
+ if ( ! isset($data['ttl']))
+ {
+ return FALSE;
+ }
+
+ return array(
+ 'expire' => $mtime + $data['ttl'],
+ 'mtime' => $mtime
+ );
+ }
+
+ return FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Determines if the driver is supported on this system.
+ *
+ * @return boolean
+ */
+ public function isSupported(): bool
+ {
+ return is_writable($this->path);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Does the heavy lifting of actually retrieving the file and
+ * verifying it's age.
+ *
+ * @param string $key
+ *
+ * @return bool|mixed
+ */
+ protected function getItem(string $key)
+ {
+ if (! is_file($this->path.$key))
+ {
+ return null;
+ }
+
+ $data = unserialize(file_get_contents($this->path.$key));
+
+ if ($data['ttl'] > 0 && time() > $data['time']+$data['ttl'])
+ {
+ unlink($this->path.$key);
+
+ return null;
+ }
+
+ return $data;
+ }
+
+ //--------------------------------------------------------------------
+
+ //--------------------------------------------------------------------
+ // SUPPORT METHODS FOR FILES
+ //--------------------------------------------------------------------
+
+ /**
+ * Writes a file to disk, or returns false if not successful.
+ *
+ * @param $path
+ * @param $data
+ * @param string $mode
+ *
+ * @return bool
+ */
+ protected function writeFile($path, $data, $mode = 'wb')
+ {
+ if (! $fp = @fopen($path, $mode))
+ {
+ return false;
+ }
+
+ flock($fp, LOCK_EX);
+
+ for ($result = $written = 0, $length = strlen($data); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($data, $written))) === false)
+ {
+ break;
+ }
+ }
+
+ flock($fp, LOCK_UN);
+ fclose($fp);
+
+ return is_int($result);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Delete Files
+ *
+ * Deletes all files contained in the supplied directory path.
+ * Files must be writable or owned by the system in order to be deleted.
+ * If the second parameter is set to TRUE, any directories contained
+ * within the supplied base directory will be nuked as well.
+ *
+ * @param string $path File path
+ * @param bool $del_dir Whether to delete any directories found in the path
+ * @param bool $htdocs Whether to skip deleting .htaccess and index page files
+ * @param int $_level Current directory depth level (default: 0; internal use only)
+ *
+ * @return bool
+ */
+ protected function deleteFiles($path, $del_dir = false, $htdocs = false, $_level = 0)
+ {
+ // Trim the trailing slash
+ $path = rtrim($path, '/\\');
+
+ if (! $current_dir = @opendir($path))
+ {
+ return false;
+ }
+
+ while (false !== ($filename = @readdir($current_dir)))
+ {
+ if ($filename !== '.' && $filename !== '..')
+ {
+ if (is_dir($path.DIRECTORY_SEPARATOR.$filename) && $filename[0] !== '.')
+ {
+ $this->deleteFiles($path.DIRECTORY_SEPARATOR.$filename, $del_dir, $htdocs, $_level+1);
+ }
+ elseif ($htdocs !== true || ! preg_match('/^(\.htaccess|index\.(html|htm|php)|web\.config)$/i', $filename))
+ {
+ @unlink($path.DIRECTORY_SEPARATOR.$filename);
+ }
+ }
+ }
+
+ closedir($current_dir);
+
+ return ($del_dir === true && $_level > 0)
+ ? @rmdir($path)
+ : true;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Get Directory File Information
+ *
+ * Reads the specified directory and builds an array containing the filenames,
+ * filesize, dates, and permissions
+ *
+ * Any sub-folders contained within the specified path are read as well.
+ *
+ * @param string path to source
+ * @param bool Look only at the top level directory specified?
+ * @param bool internal variable to determine recursion status - do not use in calls
+ *
+ * @return array
+ */
+ protected function getDirFileInfo($source_dir, $top_level_only = true, $_recursion = false)
+ {
+ static $_filedata = [];
+ $relative_path = $source_dir;
+
+ if ($fp = @opendir($source_dir))
+ {
+ // reset the array and make sure $source_dir has a trailing slash on the initial call
+ if ($_recursion === false)
+ {
+ $_filedata = [];
+ $source_dir = rtrim(realpath($source_dir), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR;
+ }
+
+ // Used to be foreach (scandir($source_dir, 1) as $file), but scandir() is simply not as fast
+ while (false !== ($file = readdir($fp)))
+ {
+ if (is_dir($source_dir.$file) && $file[0] !== '.' && $top_level_only === false)
+ {
+ $this->getDirFileInfo($source_dir.$file.DIRECTORY_SEPARATOR, $top_level_only, true);
+ }
+ elseif ($file[0] !== '.')
+ {
+ $_filedata[$file] = $this->getFileInfo($source_dir.$file);
+ $_filedata[$file]['relative_path'] = $relative_path;
+ }
+ }
+
+ closedir($fp);
+
+ return $_filedata;
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Get File Info
+ *
+ * Given a file and path, returns the name, path, size, date modified
+ * Second parameter allows you to explicitly declare what information you want returned
+ * Options are: name, server_path, size, date, readable, writable, executable, fileperms
+ * Returns FALSE if the file cannot be found.
+ *
+ * @param string path to file
+ * @param mixed array or comma separated string of information returned
+ *
+ * @return array
+ */
+ protected function getFileInfo($file, $returned_values = ['name', 'server_path', 'size', 'date'])
+ {
+ if (! file_exists($file))
+ {
+ return false;
+ }
+
+ if (is_string($returned_values))
+ {
+ $returned_values = explode(',', $returned_values);
+ }
+
+ foreach ($returned_values as $key)
+ {
+ switch ($key)
+ {
+ case 'name':
+ $fileinfo['name'] = basename($file);
+ break;
+ case 'server_path':
+ $fileinfo['server_path'] = $file;
+ break;
+ case 'size':
+ $fileinfo['size'] = filesize($file);
+ break;
+ case 'date':
+ $fileinfo['date'] = filemtime($file);
+ break;
+ case 'readable':
+ $fileinfo['readable'] = is_readable($file);
+ break;
+ case 'writable':
+ $fileinfo['writable'] = is_writable($file);
+ break;
+ case 'executable':
+ $fileinfo['executable'] = is_executable($file);
+ break;
+ case 'fileperms':
+ $fileinfo['fileperms'] = fileperms($file);
+ break;
+ }
+ }
+
+ return $fileinfo;
+ }
+
+ //--------------------------------------------------------------------
+}
\ No newline at end of file
diff --git a/system/Common.php b/system/Common.php
index bfaeb8ae1257..aaabf1dd1247 100644
--- a/system/Common.php
+++ b/system/Common.php
@@ -244,7 +244,7 @@ function service(string $name, ...$params)
{
/**
* Allow cleaner access to shared services
- *
+ *
* @param string $name
* @param array|null $params
* @return type
From 0242b6a00e64be9d62bd2e1967ea817c0e641ae6 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 22:31:49 -0500
Subject: [PATCH 0011/1807] Memcached cache driver
---
application/Config/Cache.php | 18 ++
system/Cache/Handlers/MemcachedHandler.php | 293 +++++++++++++++++++++
2 files changed, 311 insertions(+)
create mode 100644 system/Cache/Handlers/MemcachedHandler.php
diff --git a/application/Config/Cache.php b/application/Config/Cache.php
index 582c5be77d91..b164bccf4e14 100644
--- a/application/Config/Cache.php
+++ b/application/Config/Cache.php
@@ -65,6 +65,24 @@ class Cache extends BaseConfig
*/
public $prefix = '';
+ /*
+ | -------------------------------------------------------------------------
+ | Memcached settings
+ | -------------------------------------------------------------------------
+ | Your Memcached servers can be specified below, if you are using
+ | the Memcached drivers.
+ |
+ | See: https://codeigniter.com/user_guide/libraries/caching.html#memcached
+ |
+ */
+ public $memcached = [
+ 'default' => [
+ 'host' => '127.0.0.1',
+ 'port' => 11211,
+ 'weight' => 1
+ ]
+ ];
+
/*
|--------------------------------------------------------------------------
| Available Cache Handlers
diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php
new file mode 100644
index 000000000000..3fa91662723e
--- /dev/null
+++ b/system/Cache/Handlers/MemcachedHandler.php
@@ -0,0 +1,293 @@
+ [
+ 'host' => '127.0.0.1',
+ 'port' => 11211,
+ 'weight' => 1,
+ ],
+ ];
+
+ //--------------------------------------------------------------------
+
+ public function __construct($config)
+ {
+ $this->prefix = $config->prefix ?: '';
+
+ if (isset($config->memcached))
+ {
+ $this->config = $config->memcached;
+ }
+
+ $defaults = $this->config['defaults'];
+
+ if (class_exists('Memcached'))
+ {
+ $this->memcached = new Memcached();
+ }
+ elseif (class_exists('Memcache'))
+ {
+ $this->memcached = new Memcache();
+ }
+ else
+ {
+// log_message('error', 'Cache: Failed to create Memcache(d) object; extension not loaded?');
+
+ return;
+ }
+
+ foreach ($this->config as $cacheName => $cacheServer)
+ {
+ if (! isset($cacheServer['hostname']))
+ {
+// log_message('debug', 'Cache: Memcache(d) configuration "'.$cacheName.'" doesn\'t include a hostname; ignoring.');
+ continue;
+ }
+ elseif ($cacheServer['hostname'][0] === '/')
+ {
+ $cacheServer['port'] = 0;
+ }
+ elseif (empty($cacheServer['port']))
+ {
+ $cacheServer['port'] = $defaults['port'];
+ }
+
+ isset($cacheServer['weight']) OR $cacheServer['weight'] = $defaults['weight'];
+
+ if ($this->memcached instanceof Memcache)
+ {
+ // Third parameter is persistance and defaults to TRUE.
+ $this->memcached->addServer(
+ $cacheServer['hostname'],
+ $cacheServer['port'],
+ true,
+ $cacheServer['weight']
+ );
+ }
+ elseif ($this->memcached instanceof Memcached)
+ {
+ $this->memcached->addServer(
+ $cacheServer['hostname'],
+ $cacheServer['port'],
+ $cacheServer['weight']
+ );
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+
+ /**
+ * Attempts to fetch an item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function get(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $data = $this->memcached->get($key);
+
+ return is_array($data) ? $data[0] : $data;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Saves an item to the cache store.
+ *
+ * The $raw parameter is only utilized by Mamcache in order to
+ * allow usage of increment() and decrement().
+ *
+ * @param string $key Cache item name
+ * @param $value the data to save
+ * @param null $ttl Time To Live, in seconds (default 60)
+ * @param bool $raw Whether to store the raw value.
+ *
+ * @return mixed
+ */
+ public function save(string $key, $value, $ttl = null, $raw = false)
+ {
+ $key = $this->prefix.$key;
+
+ if ($raw !== true)
+ {
+ $value = [$value, time(), $ttl];
+ }
+
+ if ($this->memcached instanceof Memcached)
+ {
+ return $this->memcached->set($key, $value, $ttl);
+ }
+ elseif ($this->memcached instanceof Memcache)
+ {
+ return $this->memcached->set($key, $value, 0, $ttl);
+ }
+
+ return false;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Deletes a specific item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function delete(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ return $this->memcached->delete($key);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic incrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function increment(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ return $this->memcached->increment($key, $offset);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic decrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function decrement(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ return $this->memcached->decrement($key, $offset);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Will delete all items in the entire cache.
+ *
+ * @return mixed
+ */
+ public function clean()
+ {
+ return $this->memcached->flush();
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns information on the entire cache.
+ *
+ * The information returned and the structure of the data
+ * varies depending on the handler.
+ *
+ * @return mixed
+ */
+ public function getCacheInfo()
+ {
+ return $this->memcached->getStats();
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns detailed information about the specific item in the cache.
+ *
+ * @param string $key Cache item name.
+ *
+ * @return mixed
+ */
+ public function getMetaData(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $stored = $this->memcached->get($key);
+
+ if (count($stored) !== 3)
+ {
+ return FALSE;
+ }
+
+ list($data, $time, $ttl) = $stored;
+
+ return array(
+ 'expire' => $time + $ttl,
+ 'mtime' => $time,
+ 'data' => $data
+ );
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Determines if the driver is supported on this system.
+ *
+ * @return boolean
+ */
+ public function isSupported(): bool
+ {
+ return (extension_loaded('memcached') OR extension_loaded('memcache'));
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Class destructor
+ *
+ * Closes the connection to Memcache(d) if present.
+ */
+ public function __destruct()
+ {
+ if ($this->memcached instanceof Memcache)
+ {
+ $this->memcached->close();
+ }
+ elseif ($this->memcached instanceof Memcached)
+ {
+ $this->memcached->quit();
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+}
\ No newline at end of file
From fbf39cfe05a46ba695c6aa66c0639a35497d1944 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 22:48:57 -0500
Subject: [PATCH 0012/1807] Redis and Wincache Drivers
---
application/Config/Cache.php | 15 ++
system/Cache/Handlers/RedisHandler.php | 292 ++++++++++++++++++++++
system/Cache/Handlers/WincacheHandler.php | 188 ++++++++++++++
3 files changed, 495 insertions(+)
create mode 100644 system/Cache/Handlers/RedisHandler.php
create mode 100644 system/Cache/Handlers/WincacheHandler.php
diff --git a/application/Config/Cache.php b/application/Config/Cache.php
index b164bccf4e14..4b937aeefc46 100644
--- a/application/Config/Cache.php
+++ b/application/Config/Cache.php
@@ -83,6 +83,21 @@ class Cache extends BaseConfig
]
];
+ /*
+ | -------------------------------------------------------------------------
+ | Redis settings
+ | -------------------------------------------------------------------------
+ | Your Redis server can be specified below, if you are using
+ | the Redis drivers.
+ |
+ */
+ public $redis = [
+ 'host' => '127.0.0.1',
+ 'password' => null,
+ 'port' => 6379,
+ 'timeout' => 0,
+ ];
+
/*
|--------------------------------------------------------------------------
| Available Cache Handlers
diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php
new file mode 100644
index 000000000000..75259c057f79
--- /dev/null
+++ b/system/Cache/Handlers/RedisHandler.php
@@ -0,0 +1,292 @@
+ '127.0.0.1',
+ 'password' => null,
+ 'port' => 6379,
+ 'timeout' => 0,
+ ];
+
+ /**
+ * Redis connection
+ *
+ * @var Redis
+ */
+ protected $redis;
+
+ //--------------------------------------------------------------------
+
+ public function __construct($config)
+ {
+ $this->prefix = $config->prefix ?: '';
+
+ if (! $this->isSupported())
+ {
+// log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
+ return;
+ }
+
+ $config = $this->defaultConfig;
+
+ if (isset($config->redis))
+ {
+ $config = array_merge($this->defaultConfig, $config->redis);
+ }
+
+ $this->redis = new Redis();
+
+ try
+ {
+ if (! $this->redis->connect($config['host'], ($config['host'][0] === '/' ? 0
+ : $config['port']), $config['timeout'])
+ )
+ {
+// log_message('error', 'Cache: Redis connection failed. Check your configuration.');
+ }
+
+ if (isset($config['password']) && ! $this->redis->auth($config['password']))
+ {
+// log_message('error', 'Cache: Redis authentication failed.');
+ }
+ }
+ catch (RedisException $e)
+ {
+// log_message('error', 'Cache: Redis connection refused ('.$e->getMessage().')');
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Attempts to fetch an item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function get(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $data = $this->redis->hMGet($key, ['__ci_type', '__ci_value']);
+
+ if (! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === false)
+ {
+ return null;
+ }
+
+ switch ($data['__ci_type'])
+ {
+ case 'array':
+ case 'object':
+ return unserialize($data['__ci_value']);
+ case 'boolean':
+ case 'integer':
+ case 'double': // Yes, 'double' is returned and NOT 'float'
+ case 'string':
+ case 'NULL':
+ return settype($data['__ci_value'], $data['__ci_type'])
+ ? $data['__ci_value']
+ : null;
+ case 'resource':
+ default:
+ return null;
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Saves an item to the cache store.
+ *
+ * The $raw parameter is only utilized by Mamcache in order to
+ * allow usage of increment() and decrement().
+ *
+ * @param string $key Cache item name
+ * @param $value the data to save
+ * @param null $ttl Time To Live, in seconds (default 60)
+ * @param bool $raw Whether to store the raw value.
+ *
+ * @return mixed
+ */
+ public function save(string $key, $value, $ttl = null, $raw = false)
+ {
+ $key = $this->prefix.$key;
+
+ switch ($data_type = gettype($value))
+ {
+ case 'array':
+ case 'object':
+ $value = serialize($value);
+ break;
+ case 'boolean':
+ case 'integer':
+ case 'double': // Yes, 'double' is returned and NOT 'float'
+ case 'string':
+ case 'NULL':
+ break;
+ case 'resource':
+ default:
+ return false;
+ }
+
+ if (! $this->redis->hMSet($key, ['__ci_type' => $data_type, '__ci_value' => $value]))
+ {
+ return false;
+ }
+ elseif ($ttl)
+ {
+ $this->redis->expireAt($key, time()+$ttl);
+ }
+
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Deletes a specific item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function delete(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ return ($this->redis->delete($key) === 1);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic incrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function increment(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ return $this->redis->hIncrBy($key, 'data', $offset);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic decrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function decrement(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ return $this->redis->hIncrBy($key, 'data', -$offset);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Will delete all items in the entire cache.
+ *
+ * @return mixed
+ */
+ public function clean()
+ {
+ return $this->redis->flushDB();
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns information on the entire cache.
+ *
+ * The information returned and the structure of the data
+ * varies depending on the handler.
+ *
+ * @return mixed
+ */
+ public function getCacheInfo()
+ {
+ return $this->redis->info();
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns detailed information about the specific item in the cache.
+ *
+ * @param string $key Cache item name.
+ *
+ * @return mixed
+ */
+ public function getMetaData(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $value = $this->get($key);
+
+ if ($value !== FALSE)
+ {
+ return array(
+ 'expire' => time() + $this->redis->ttl($key),
+ 'data' => $value
+ );
+ }
+
+ return FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Determines if the driver is supported on this system.
+ *
+ * @return boolean
+ */
+ public function isSupported(): bool
+ {
+ return extension_loaded('redis');
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Class destructor
+ *
+ * Closes the connection to Memcache(d) if present.
+ */
+ public function __destruct()
+ {
+ if ($this->redis)
+ {
+ $this->redis->close();
+ }
+ }
+
+ //--------------------------------------------------------------------
+
+}
\ No newline at end of file
diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php
new file mode 100644
index 000000000000..c60101ca789a
--- /dev/null
+++ b/system/Cache/Handlers/WincacheHandler.php
@@ -0,0 +1,188 @@
+prefix = $config->prefix ?: '';
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Attempts to fetch an item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function get(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ $success = FALSE;
+ $data = wincache_ucache_get($key, $success);
+
+ // Success returned by reference from wincache_ucache_get()
+ return ($success) ? $data : FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Saves an item to the cache store.
+ *
+ * The $raw parameter is only utilized by Mamcache in order to
+ * allow usage of increment() and decrement().
+ *
+ * @param string $key Cache item name
+ * @param $value the data to save
+ * @param null $ttl Time To Live, in seconds (default 60)
+ * @param bool $raw Whether to store the raw value.
+ *
+ * @return mixed
+ */
+ public function save(string $key, $value, $ttl = 60, $raw = false)
+ {
+ $key = $this->prefix.$key;
+
+ return wincache_ucache_set($key, $value, $ttl);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Deletes a specific item from the cache store.
+ *
+ * @param string $key Cache item name
+ *
+ * @return mixed
+ */
+ public function delete(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ return wincache_ucache_delete($key);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic incrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function increment(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ $success = FALSE;
+ $value = wincache_ucache_inc($key, $offset, $success);
+
+ return ($success === TRUE) ? $value : FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Performs atomic decrementation of a raw stored value.
+ *
+ * @param string $key Cache ID
+ * @param int $offset Step/value to increase by
+ *
+ * @return mixed
+ */
+ public function decrement(string $key, $offset = 1)
+ {
+ $key = $this->prefix.$key;
+
+ $success = FALSE;
+ $value = wincache_ucache_dec($key, $offset, $success);
+
+ return ($success === TRUE) ? $value : FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Will delete all items in the entire cache.
+ *
+ * @return mixed
+ */
+ public function clean()
+ {
+ return wincache_ucache_clear();
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns information on the entire cache.
+ *
+ * The information returned and the structure of the data
+ * varies depending on the handler.
+ *
+ * @return mixed
+ */
+ public function getCacheInfo()
+ {
+ return wincache_ucache_info(TRUE);
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Returns detailed information about the specific item in the cache.
+ *
+ * @param string $key Cache item name.
+ *
+ * @return mixed
+ */
+ public function getMetaData(string $key)
+ {
+ $key = $this->prefix.$key;
+
+ if ($stored = wincache_ucache_info(FALSE, $key))
+ {
+ $age = $stored['ucache_entries'][1]['age_seconds'];
+ $ttl = $stored['ucache_entries'][1]['ttl_seconds'];
+ $hitcount = $stored['ucache_entries'][1]['hitcount'];
+
+ return array(
+ 'expire' => $ttl - $age,
+ 'hitcount' => $hitcount,
+ 'age' => $age,
+ 'ttl' => $ttl
+ );
+ }
+
+ return FALSE;
+ }
+
+ //--------------------------------------------------------------------
+
+ /**
+ * Determines if the driver is supported on this system.
+ *
+ * @return boolean
+ */
+ public function isSupported(): bool
+ {
+ return (extension_loaded('wincache') && ini_get('wincache.ucenabled'));
+ }
+
+ //--------------------------------------------------------------------
+
+}
\ No newline at end of file
From 346513fb94ee0cec728db9095f1ee7e57086c16c Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 22:51:21 -0500
Subject: [PATCH 0013/1807] Default TTL for all cache handlers
---
system/Cache/Handlers/DummyHandler.php | 2 +-
system/Cache/Handlers/FileHandler.php | 2 +-
system/Cache/Handlers/MemcachedHandler.php | 2 +-
system/Cache/Handlers/RedisHandler.php | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/system/Cache/Handlers/DummyHandler.php b/system/Cache/Handlers/DummyHandler.php
index e301a9e57f7e..cc8aadaee099 100644
--- a/system/Cache/Handlers/DummyHandler.php
+++ b/system/Cache/Handlers/DummyHandler.php
@@ -29,7 +29,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = null, $raw = false)
+ public function save(string $key, $value, $ttl = 60, $raw = false)
{
return true;
}
diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php
index 8e5f3acd9cd5..e2139f93b9da 100644
--- a/system/Cache/Handlers/FileHandler.php
+++ b/system/Cache/Handlers/FileHandler.php
@@ -62,7 +62,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = null, $raw = false)
+ public function save(string $key, $value, $ttl = 60, $raw = false)
{
$key = $this->prefix.$key;
diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php
index 3fa91662723e..e21ef2cd9bd1 100644
--- a/system/Cache/Handlers/MemcachedHandler.php
+++ b/system/Cache/Handlers/MemcachedHandler.php
@@ -130,7 +130,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = null, $raw = false)
+ public function save(string $key, $value, $ttl = 60, $raw = false)
{
$key = $this->prefix.$key;
diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php
index 75259c057f79..0691476e6a0f 100644
--- a/system/Cache/Handlers/RedisHandler.php
+++ b/system/Cache/Handlers/RedisHandler.php
@@ -124,7 +124,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = null, $raw = false)
+ public function save(string $key, $value, $ttl = 60, $raw = false)
{
$key = $this->prefix.$key;
From e05df8784a3eceb0e3375c1d0bd5eb16d52d2ec1 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:03:35 -0500
Subject: [PATCH 0014/1807] Refactoring cache handler init. Consistent type
hinting
---
system/Cache/CacheFactory.php | 2 ++
system/Cache/Handlers/DummyHandler.php | 16 ++++++++++---
system/Cache/Handlers/FileHandler.php | 15 ++++++++++---
system/Cache/Handlers/MemcachedHandler.php | 14 +++++++++---
system/Cache/Handlers/RedisHandler.php | 26 ++++++++++++----------
system/Cache/Handlers/WincacheHandler.php | 18 +++++++++++----
6 files changed, 66 insertions(+), 25 deletions(-)
diff --git a/system/Cache/CacheFactory.php b/system/Cache/CacheFactory.php
index 41b4d2ee1297..2fca1243b71c 100644
--- a/system/Cache/CacheFactory.php
+++ b/system/Cache/CacheFactory.php
@@ -54,6 +54,8 @@ public static function getHandler($config, string $handler = null, string $backu
}
}
+ $adapter->initialize();
+
return $adapter;
}
diff --git a/system/Cache/Handlers/DummyHandler.php b/system/Cache/Handlers/DummyHandler.php
index cc8aadaee099..5d95688461ac 100644
--- a/system/Cache/Handlers/DummyHandler.php
+++ b/system/Cache/Handlers/DummyHandler.php
@@ -2,6 +2,16 @@
class DummyHandler implements CacheInterface
{
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize()
+ {
+ // Nothing to see here...
+ }
+
+ //--------------------------------------------------------------------
+
/**
* Attempts to fetch an item from the cache store.
*
@@ -29,7 +39,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = 60, $raw = false)
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false)
{
return true;
}
@@ -58,7 +68,7 @@ public function delete(string $key)
*
* @return mixed
*/
- public function increment(string $key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
return true;
}
@@ -73,7 +83,7 @@ public function increment(string $key, $offset = 1)
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
return true;
}
diff --git a/system/Cache/Handlers/FileHandler.php b/system/Cache/Handlers/FileHandler.php
index e2139f93b9da..3eaddce939e4 100644
--- a/system/Cache/Handlers/FileHandler.php
+++ b/system/Cache/Handlers/FileHandler.php
@@ -30,6 +30,15 @@ public function __construct($config)
//--------------------------------------------------------------------
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize()
+ {
+ // Not to see here...
+ }
+
+ //--------------------------------------------------------------------
/**
* Attempts to fetch an item from the cache store.
@@ -62,7 +71,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = 60, $raw = false)
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false)
{
$key = $this->prefix.$key;
@@ -110,7 +119,7 @@ public function delete(string $key)
*
* @return mixed
*/
- public function increment(string $key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
@@ -142,7 +151,7 @@ public function increment(string $key, $offset = 1)
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php
index e21ef2cd9bd1..22f81159b545 100644
--- a/system/Cache/Handlers/MemcachedHandler.php
+++ b/system/Cache/Handlers/MemcachedHandler.php
@@ -39,7 +39,15 @@ public function __construct($config)
{
$this->config = $config->memcached;
}
+ }
+
+ //--------------------------------------------------------------------
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize()
+ {
$defaults = $this->config['defaults'];
if (class_exists('Memcached'))
@@ -130,7 +138,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = 60, $raw = false)
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false)
{
$key = $this->prefix.$key;
@@ -177,7 +185,7 @@ public function delete(string $key)
*
* @return mixed
*/
- public function increment(string $key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
@@ -194,7 +202,7 @@ public function increment(string $key, $offset = 1)
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php
index 0691476e6a0f..3e44eb4fcec5 100644
--- a/system/Cache/Handlers/RedisHandler.php
+++ b/system/Cache/Handlers/RedisHandler.php
@@ -15,7 +15,7 @@ class RedisHandler implements CacheInterface
* @static
* @var array
*/
- protected $defaultConfig = [
+ protected $config = [
'host' => '127.0.0.1',
'password' => null,
'port' => 6379,
@@ -35,18 +35,20 @@ public function __construct($config)
{
$this->prefix = $config->prefix ?: '';
- if (! $this->isSupported())
+ if (isset($config->redis))
{
-// log_message('error', 'Cache: Failed to create Redis object; extension not loaded?');
- return;
+ $this->config = array_merge($this->config, $config->redis);
}
+ }
- $config = $this->defaultConfig;
+ //--------------------------------------------------------------------
- if (isset($config->redis))
- {
- $config = array_merge($this->defaultConfig, $config->redis);
- }
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize()
+ {
+ $config = $this->config;
$this->redis = new Redis();
@@ -124,7 +126,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = 60, $raw = false)
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false)
{
$key = $this->prefix.$key;
@@ -183,7 +185,7 @@ public function delete(string $key)
*
* @return mixed
*/
- public function increment(string $key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
@@ -200,7 +202,7 @@ public function increment(string $key, $offset = 1)
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php
index c60101ca789a..803f281c6a87 100644
--- a/system/Cache/Handlers/WincacheHandler.php
+++ b/system/Cache/Handlers/WincacheHandler.php
@@ -17,7 +17,17 @@ public function __construct($config)
}
//--------------------------------------------------------------------
-
+
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize()
+ {
+ // Nothing to see here...
+ }
+
+ //--------------------------------------------------------------------
+
/**
* Attempts to fetch an item from the cache store.
*
@@ -51,7 +61,7 @@ public function get(string $key)
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = 60, $raw = false)
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false)
{
$key = $this->prefix.$key;
@@ -84,7 +94,7 @@ public function delete(string $key)
*
* @return mixed
*/
- public function increment(string $key, $offset = 1)
+ public function increment(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
@@ -104,7 +114,7 @@ public function increment(string $key, $offset = 1)
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1)
+ public function decrement(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
From 26251ae72952be7dfb13188cfe341803c225b98e Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:24:34 -0500
Subject: [PATCH 0015/1807] Missed use statement
---
system/Cache/CacheFactory.php | 4 ++--
system/Cache/CacheInterface.php | 15 +++++++++++----
system/Cache/Handlers/DummyHandler.php | 2 ++
system/Cache/Handlers/FileHandler.php | 4 +++-
system/Cache/Handlers/MemcachedHandler.php | 2 ++
system/Cache/Handlers/RedisHandler.php | 2 ++
system/Cache/Handlers/WincacheHandler.php | 2 ++
7 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/system/Cache/CacheFactory.php b/system/Cache/CacheFactory.php
index 2fca1243b71c..cee74ebea577 100644
--- a/system/Cache/CacheFactory.php
+++ b/system/Cache/CacheFactory.php
@@ -27,13 +27,13 @@ public static function getHandler($config, string $handler = null, string $backu
if (! isset($config->handler) || ! isset($config->backupHandler))
{
- throw new \InvalidArgumentException('Cache config must have a handler and backupHanlder set.');
+ throw new \InvalidArgumentException('Cache config must have a handler and backupHandler set.');
}
$handler = ! empty($handler) ? $handler : $config->handler;
$backup = ! empty($backup) ? $backup : $config->backupHandler;
- if (! in_array($handler, $config->validHandlers) || ! in_array($backup, $config->validHandlers))
+ if (! array_key_exists($handler, $config->validHandlers) || ! array_key_exists($backup, $config->validHandlers))
{
throw new \InvalidArgumentException('Cache config has an invalid handler or backup handler specified.');
}
diff --git a/system/Cache/CacheInterface.php b/system/Cache/CacheInterface.php
index 35ae33f270fd..4a68d273f588 100644
--- a/system/Cache/CacheInterface.php
+++ b/system/Cache/CacheInterface.php
@@ -2,6 +2,13 @@
interface CacheInterface
{
+ /**
+ * Takes care of any handler-specific setup that must be done.
+ */
+ public function initialize();
+
+ //--------------------------------------------------------------------
+
/**
* Attempts to fetch an item from the cache store.
*
@@ -26,7 +33,7 @@ public function get(string $key);
*
* @return mixed
*/
- public function save(string $key, $value, $ttl = null, $raw = false);
+ public function save(string $key, $value, int $ttl = 60, bool $raw = false);
//--------------------------------------------------------------------
@@ -49,7 +56,7 @@ public function delete(string $key);
*
* @return mixed
*/
- public function increment(string $key, $offset = 1);
+ public function increment(string $key, int $offset = 1);
//--------------------------------------------------------------------
@@ -61,7 +68,7 @@ public function increment(string $key, $offset = 1);
*
* @return mixed
*/
- public function decrement(string $key, $offset = 1);
+ public function decrement(string $key, int $offset = 1);
//--------------------------------------------------------------------
@@ -96,7 +103,7 @@ public function getCacheInfo();
public function getMetaData(string $key);
//--------------------------------------------------------------------
-
+
/**
* Determines if the driver is supported on this system.
*
diff --git a/system/Cache/Handlers/DummyHandler.php b/system/Cache/Handlers/DummyHandler.php
index 5d95688461ac..5a6f40dfc528 100644
--- a/system/Cache/Handlers/DummyHandler.php
+++ b/system/Cache/Handlers/DummyHandler.php
@@ -1,5 +1,7 @@
getItem($key);
- return is_array($data) ? $data['data'] : null;
+ return is_array($data) ? $data['data'] : false;
}
//--------------------------------------------------------------------
diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php
index 22f81159b545..50452f357e51 100644
--- a/system/Cache/Handlers/MemcachedHandler.php
+++ b/system/Cache/Handlers/MemcachedHandler.php
@@ -1,5 +1,7 @@
Date: Mon, 27 Jun 2016 23:24:55 -0500
Subject: [PATCH 0016/1807] Adding Cache files
---
system/Config/AutoloadConfig.php | 13 ++++++++++---
1 file changed, 10 insertions(+), 3 deletions(-)
diff --git a/system/Config/AutoloadConfig.php b/system/Config/AutoloadConfig.php
index d06770b2dfb2..b50af3eb9790 100644
--- a/system/Config/AutoloadConfig.php
+++ b/system/Config/AutoloadConfig.php
@@ -39,7 +39,7 @@
/**
* AUTO-LOADER
- *
+ *
* This file defines the namespaces and class maps so the Autoloader
* can find the files as needed.
*/
@@ -47,13 +47,13 @@ class AutoloadConfig
{
/**
* Array of namespaces for autoloading.
- * @var type
+ * @var type
*/
public $psr4 = [];
/**
* Map of class names and locations
- * @var type
+ * @var type
*/
public $classmap = [];
@@ -114,6 +114,13 @@ public function __construct()
'CodeIgniter\CodeIgniter' => BASEPATH.'CodeIgniter.php',
'CodeIgniter\CLI\CLI' => BASEPATH.'CLI/CLI.php',
'CodeIgniter\Loader' => BASEPATH.'Loader.php',
+ 'CodeIgniter\Cache\CacheFactory' => BASEPATH.'Cache/CacheFactory.php',
+ 'CodeIgniter\Cache\CacheInterface' => BASEPATH.'Cache/CacheInterface.php',
+ 'CodeIgniter\Cache\Handlers\DummyHandler' => BASEPATH.'Cache/Handlers/DummyHandler.php',
+ 'CodeIgniter\Cache\Handlers\FileHandler' => BASEPATH.'Cache/Handlers/FileHandler.php',
+ 'CodeIgniter\Cache\Handlers\MemcachedHandler' => BASEPATH.'Cache/Handlers/MemcachedHandler.php',
+ 'CodeIgniter\Cache\Handlers\RedisHandler' => BASEPATH.'Cache/Handlers/RedisHandler.php',
+ 'CodeIgniter\Cache\Handlers\WincacheHandler' => BASEPATH.'Cache/Handlers/WincacheHandler.php',
'CodeIgniter\Controller' => BASEPATH.'Controller.php',
'CodeIgniter\Config\AutoloadConfig' => BASEPATH.'Config/Autoload.php',
'CodeIgniter\Config\BaseConfig' => BASEPATH.'Config/BaseConfig.php',
From 4512606f7a6ac2d4c930118e5e74e9a2ae02ce6f Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:25:13 -0500
Subject: [PATCH 0017/1807] Don't allow setting 'path'
---
system/Config/BaseConfig.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/system/Config/BaseConfig.php b/system/Config/BaseConfig.php
index 28cc3f7e0dfb..e3dbad46baf7 100644
--- a/system/Config/BaseConfig.php
+++ b/system/Config/BaseConfig.php
@@ -108,7 +108,7 @@ protected function getEnvValue(string $property, string $prefix, string $shortPr
{
return $value;
}
- elseif (($value = getenv($property)) !== false)
+ elseif (($value = getenv($property)) !== false && $property != 'path')
{
return $value;
}
From 574bfa23fe1e555e2e91a55ceafdc98d00531e69 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:34:44 -0500
Subject: [PATCH 0018/1807] Return false on no values from Caches::get
---
application/Config/Cache.php | 14 ++++----
system/Cache/Handlers/RedisHandler.php | 6 ++--
system/Cache/Handlers/WincacheHandler.php | 42 +++++++++++------------
3 files changed, 32 insertions(+), 30 deletions(-)
diff --git a/application/Config/Cache.php b/application/Config/Cache.php
index 4b937aeefc46..e297929b42a4 100644
--- a/application/Config/Cache.php
+++ b/application/Config/Cache.php
@@ -1,5 +1,7 @@
\CodeIgniter\Cache\Handlers\DummyHandler::class,
-// 'file' => \CodeIgniter\Cache\Handlers\FileHandler::class,
-// 'memcached' => \CodeIgniter\Cache\Handlers\MemcachedHandler::class,
-// 'redis' => \CodeIgniter\Cache\Handlers\RedisHandler::class,
-// 'wincache' => \CodeIgniter\Cache\Handlers\WincacheHandler::class,
+ 'file' => \CodeIgniter\Cache\Handlers\FileHandler::class,
+ 'memcached' => \CodeIgniter\Cache\Handlers\MemcachedHandler::class,
+ 'redis' => \CodeIgniter\Cache\Handlers\RedisHandler::class,
+ 'wincache' => \CodeIgniter\Cache\Handlers\WincacheHandler::class,
];
}
diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php
index 1ba0589c4d37..3563a6f5d8eb 100644
--- a/system/Cache/Handlers/RedisHandler.php
+++ b/system/Cache/Handlers/RedisHandler.php
@@ -91,7 +91,7 @@ public function get(string $key)
if (! isset($data['__ci_type'], $data['__ci_value']) OR $data['__ci_value'] === false)
{
- return null;
+ return false;
}
switch ($data['__ci_type'])
@@ -106,10 +106,10 @@ public function get(string $key)
case 'NULL':
return settype($data['__ci_value'], $data['__ci_type'])
? $data['__ci_value']
- : null;
+ : false;
case 'resource':
default:
- return null;
+ return false;
}
}
diff --git a/system/Cache/Handlers/WincacheHandler.php b/system/Cache/Handlers/WincacheHandler.php
index 781182f0fde2..adac0d91a129 100644
--- a/system/Cache/Handlers/WincacheHandler.php
+++ b/system/Cache/Handlers/WincacheHandler.php
@@ -25,7 +25,7 @@ public function __construct($config)
*/
public function initialize()
{
- // Nothing to see here...
+ // Nothing to see here...
}
//--------------------------------------------------------------------
@@ -41,11 +41,11 @@ public function get(string $key)
{
$key = $this->prefix.$key;
- $success = FALSE;
- $data = wincache_ucache_get($key, $success);
+ $success = false;
+ $data = wincache_ucache_get($key, $success);
// Success returned by reference from wincache_ucache_get()
- return ($success) ? $data : FALSE;
+ return ($success) ? $data : false;
}
//--------------------------------------------------------------------
@@ -100,10 +100,10 @@ public function increment(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
- $success = FALSE;
- $value = wincache_ucache_inc($key, $offset, $success);
+ $success = false;
+ $value = wincache_ucache_inc($key, $offset, $success);
- return ($success === TRUE) ? $value : FALSE;
+ return ($success === true) ? $value : false;
}
//--------------------------------------------------------------------
@@ -120,10 +120,10 @@ public function decrement(string $key, int $offset = 1)
{
$key = $this->prefix.$key;
- $success = FALSE;
- $value = wincache_ucache_dec($key, $offset, $success);
+ $success = false;
+ $value = wincache_ucache_dec($key, $offset, $success);
- return ($success === TRUE) ? $value : FALSE;
+ return ($success === true) ? $value : false;
}
//--------------------------------------------------------------------
@@ -150,7 +150,7 @@ public function clean()
*/
public function getCacheInfo()
{
- return wincache_ucache_info(TRUE);
+ return wincache_ucache_info(true);
}
//--------------------------------------------------------------------
@@ -166,21 +166,21 @@ public function getMetaData(string $key)
{
$key = $this->prefix.$key;
- if ($stored = wincache_ucache_info(FALSE, $key))
+ if ($stored = wincache_ucache_info(false, $key))
{
- $age = $stored['ucache_entries'][1]['age_seconds'];
- $ttl = $stored['ucache_entries'][1]['ttl_seconds'];
+ $age = $stored['ucache_entries'][1]['age_seconds'];
+ $ttl = $stored['ucache_entries'][1]['ttl_seconds'];
$hitcount = $stored['ucache_entries'][1]['hitcount'];
- return array(
- 'expire' => $ttl - $age,
- 'hitcount' => $hitcount,
- 'age' => $age,
- 'ttl' => $ttl
- );
+ return [
+ 'expire' => $ttl-$age,
+ 'hitcount' => $hitcount,
+ 'age' => $age,
+ 'ttl' => $ttl,
+ ];
}
- return FALSE;
+ return false;
}
//--------------------------------------------------------------------
From ee0cbacb6f580d324f37cc939acbb63bdc4306c7 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:35:32 -0500
Subject: [PATCH 0019/1807] Add cache common function
---
system/Common.php | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
diff --git a/system/Common.php b/system/Common.php
index aaabf1dd1247..6e3544588beb 100644
--- a/system/Common.php
+++ b/system/Common.php
@@ -53,6 +53,38 @@
// Services Convenience Functions
//--------------------------------------------------------------------
+if (! function_exists('cache'))
+{
+ /**
+ * A convenience method that provides access to the Cache
+ * object. If no parameter is provided, will return the object,
+ * otherwise, will attempt to return the cached value.
+ *
+ * Examples:
+ * cache()->save('foo', 'bar');
+ * $foo = cache('bar');
+ *
+ * @param string|null $key
+ *
+ * @return mixed
+ */
+ function cache(string $key = null)
+ {
+ $cache = \Config\Services::cache();
+
+ // No params - return cache object
+ if (is_null($key))
+ {
+ return $cache;
+ }
+
+ // Still here? Retrieve the value.
+ return $cache->get($key);
+ }
+}
+
+//--------------------------------------------------------------------
+
if ( ! function_exists('view'))
{
/**
From 54975893a6d25ef91e70115eebbd5c609339d745 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Mon, 27 Jun 2016 23:44:29 -0500
Subject: [PATCH 0020/1807] [ci skip] Adding docs for cache common function
---
.../source/general/common_functions.rst | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst
index e3daf5491af8..07c448be1437 100644
--- a/user_guide_src/source/general/common_functions.rst
+++ b/user_guide_src/source/general/common_functions.rst
@@ -15,6 +15,21 @@ Global Functions
Service Accessors
=================
+.. php:function:: cache ( [$key] )
+
+ :param string $key: The cache name of the item to retrieve from cache (Optional)
+ :returns: Either the cache object, or the item retrieved from the cache
+ :rtype: mixed
+
+ If no $key is provided, will return the Cache engine instance. If a $key
+ is provided, will return the value of $key as stored in the cache currently,
+ or false if no value is found.
+
+ Examples::
+
+ $foo = cache('foo');
+ $cache = cache();
+
.. php:function:: esc ( $data, $context='html' [, $encoding])
:param string|array $data: The information to be escaped.
From 738ff0b7c984a4e1aadde125274758b7f63d92f5 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 00:06:47 -0500
Subject: [PATCH 0021/1807] [ci skip] Cache library documentation
---
system/Cache/Handlers/RedisHandler.php | 3 +-
user_guide_src/source/libraries/caching.rst | 246 ++++++++++++++++++++
2 files changed, 248 insertions(+), 1 deletion(-)
create mode 100644 user_guide_src/source/libraries/caching.rst
diff --git a/system/Cache/Handlers/RedisHandler.php b/system/Cache/Handlers/RedisHandler.php
index 3563a6f5d8eb..725b14e2ed02 100644
--- a/system/Cache/Handlers/RedisHandler.php
+++ b/system/Cache/Handlers/RedisHandler.php
@@ -1,6 +1,7 @@
getMessage().')');
+ throw new CriticalError('Cache: Redis connection refused ('.$e->getMessage().')');
}
}
diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst
new file mode 100644
index 000000000000..4f204e2ae2f5
--- /dev/null
+++ b/user_guide_src/source/libraries/caching.rst
@@ -0,0 +1,246 @@
+##############
+Caching Driver
+##############
+
+CodeIgniter features wrappers around some of the most popular forms of
+fast and dynamic caching. All but file-based caching require specific
+server requirements, and a Fatal Exception will be thrown if server
+requirements are not met.
+
+.. contents::
+:local:
+
+*************
+Example Usage
+*************
+
+The following example shows a common usage pattern within your controllers.
+
+::
+
+ if ( ! $foo = cache('foo'))
+ {
+ echo 'Saving to the cache!
';
+ $foo = 'foobarbaz!';
+
+ // Save into the cache for 5 minutes
+ cache()->save('foo', $foo, 300);
+ }
+
+ echo $foo;
+
+You can grab an instance of the cache engine directly through the Services class::
+
+ $cache = \Config\Services::cache();
+
+ $foo = $cache->get('foo');
+
+=====================
+Configuring the Cache
+=====================
+
+All configuration for the cache engine is done in **application/Config/Cache.php**. In that file,
+the following items are available.
+
+**$handler**
+
+The is the name of the handler that should be used as the primary handler when starting up the engine.
+Available names are: dummy, file, memcached, redis, wincache.
+
+**$backupHandler**
+
+In the case that the first choice $hanlder is not available, this is the next cache handler to load.
+This is commonly the **file** handler since the file system is always available, but may not fit
+more complex, multi-server setups.
+
+**$prefix**
+
+If you have more than one application using the same cache storage, you can add a custom prefix
+here that is prepended to all key names.
+
+**$path**
+
+This is used by the ``file`` handler to show where it should save the cache files to.
+
+**$memcached**
+
+This is an array of servers that will be used when using the ``Memcache(d)`` handler.
+
+**$redis**
+
+The settings for the Redis server that you wish to use when using the ``Redis`` handler.
+
+===============
+Class Reference
+===============
+
+ .. php:method:: isSupported($handler)
+
+ :param string $handler: the name of the caching handler
+ :returns: TRUE if supported, FALSE if not
+ :rtype: bool
+
+ .. php:method:: get($id)
+
+ :param string $id: Cache item name
+ :returns: Item value or FALSE if not found
+ :rtype: mixed
+
+ This method will attempt to fetch an item from the cache store. If the
+ item does not exist, the method will return FALSE.
+ ::
+
+ $foo = $cache->get('my_cached_item');
+
+ .. php:method:: save($id, $data[, $ttl = 60[, $raw = FALSE]])
+
+ :param string $id: Cache item name
+ :param mixed $data: the data to save
+ :param int $ttl: Time To Live, in seconds (default 60)
+ :param bool $raw: Whether to store the raw value
+ :returns: TRUE on success, FALSE on failure
+ :rtype: string
+
+ This method will save an item to the cache store. If saving fails, the
+ method will return FALSE.
+ ::
+
+ $cache->save('cache_item_id', 'data_to_cache');
+
+ .. note:: The ``$raw`` parameter is only utilized by Memcache,
+in order to allow usage of ``increment()`` and ``decrement()``.
+
+ .. php:method:: delete($id)
+
+ :param string $id: name of cached item
+ :returns: TRUE on success, FALSE on failure
+ :rtype: bool
+
+ This method will delete a specific item from the cache store. If item
+ deletion fails, the method will return FALSE.
+ ::
+
+ $cache->delete('cache_item_id');
+
+ .. php:method:: increment($id[, $offset = 1])
+
+ :param string $id: Cache ID
+ :param int $offset: Step/value to add
+ :returns: New value on success, FALSE on failure
+ :rtype: mixed
+
+ Performs atomic incrementation of a raw stored value.
+ ::
+
+ // 'iterator' has a value of 2
+
+ $cache->increment('iterator'); // 'iterator' is now 3
+
+ $cache->increment('iterator', 3); // 'iterator' is now 6
+
+ .. php:method:: decrement($id[, $offset = 1])
+
+ :param string $id: Cache ID
+ :param int $offset: Step/value to reduce by
+ :returns: New value on success, FALSE on failure
+ :rtype: mixed
+
+ Performs atomic decrementation of a raw stored value.
+ ::
+
+ // 'iterator' has a value of 6
+
+ $cache->decrement('iterator'); // 'iterator' is now 5
+
+ $cache->decrement('iterator', 2); // 'iterator' is now 3
+
+ .. php:method:: clean()
+
+ :returns: TRUE on success, FALSE on failure
+ :rtype: bool
+
+ This method will 'clean' the entire cache. If the deletion of the
+ cache files fails, the method will return FALSE.
+ ::
+
+ $cache->clean();
+
+ .. php:method:: cache_info()
+
+ :returns: Information on the entire cache database
+ :rtype: mixed
+
+ This method will return information on the entire cache.
+ ::
+
+ var_dump($cache->cache_info());
+
+ .. note:: The information returned and the structure of the data is dependent
+on which adapter is being used.
+
+ .. php:method:: getMetadata($id)
+
+ :param string $id: Cache item name
+ :returns: Metadata for the cached item
+ :rtype: mixed
+
+ This method will return detailed information on a specific item in the
+ cache.
+ ::
+
+ var_dump($cache->getMetadata('my_cached_item'));
+
+ .. note:: The information returned and the structure of the data is dependent
+on which adapter is being used.
+
+*******
+Drivers
+*******
+
+File-based Caching
+==================
+
+Unlike caching from the Output Class, the driver file-based caching
+allows for pieces of view files to be cached. Use this with care, and
+make sure to benchmark your application, as a point can come where disk
+I/O will negate positive gains by caching.
+
+Memcached Caching
+=================
+
+Multiple Memcached servers can be specified in the cache configuration file.
+
+For more information on Memcached, please see
+`http://php.net/memcached `_.
+
+WinCache Caching
+================
+
+Under Windows, you can also utilize the WinCache driver.
+
+For more information on WinCache, please see
+`http://php.net/wincache `_.
+
+Redis Caching
+=============
+
+Redis is an in-memory key-value store which can operate in LRU cache mode.
+To use it, you need `Redis server and phpredis PHP extension `_.
+
+Config options to connect to redis server must be stored in the application/config/redis.php file.
+Available options are::
+
+ $config['host'] = '127.0.0.1';
+ $config['password'] = NULL;
+ $config['port'] = 6379;
+ $config['timeout'] = 0;
+
+For more information on Redis, please see
+`http://redis.io `_.
+
+Dummy Cache
+===========
+
+This is a caching backend that will always 'miss.' It stores no data,
+but lets you keep your caching code in place in environments that don't
+support your chosen cache.
\ No newline at end of file
From 59fb85c2fbe236025e0522bc0b7f791f836116ec Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 21:59:55 -0500
Subject: [PATCH 0022/1807] Tutorial corrections
---
user_guide_src/source/tutorial/news_section.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst
index b25eb63acf11..33ec3dabba04 100644
--- a/user_guide_src/source/tutorial/news_section.rst
+++ b/user_guide_src/source/tutorial/news_section.rst
@@ -65,7 +65,7 @@ following code to your model.
{
if ($slug === false)
{
- return $this->findAll();
+ $this->findAll();
}
return $this->asArray()
@@ -195,13 +195,13 @@ add some code to the controller and create a new view. Go back to the
if (empty($data['news']))
{
- throw new \CodeIgniter\PageNotFoundException('Cannot page the page: '. $slug);
+ throw new \CodeIgniter\PageNotFoundException('Cannot find the page: '. $slug);
}
- $data['title'] = $data['news'][0]['title'];
+ $data['title'] = $data['news']['title'];
echo view('Templates/Header', $data);
- echo view('News/Index', $data);
+ echo view('News/View', $data);
echo view('Templates/Footer');
}
@@ -214,7 +214,7 @@ The only things left to do is create the corresponding view at
'.$news['title'].'';
- echo $$news['text'];
+ echo $news['text'];
Routing
-------
From 7061d4ec9db46191c1c999cfa0a4aa0c2a8a8650 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 22:04:41 -0500
Subject: [PATCH 0023/1807] Defaulting controllers to be namespaced to
encourage use of Namespaces now.
---
application/Config/Routes.php | 2 +-
application/Controllers/Home.php | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/application/Config/Routes.php b/application/Config/Routes.php
index de43652a760a..d10976275bfd 100644
--- a/application/Config/Routes.php
+++ b/application/Config/Routes.php
@@ -58,7 +58,7 @@
* Controllers when no specific route has been defined. If false,
* only routes that have been defined here will be available.
*/
-$routes->setDefaultNamespace('');
+$routes->setDefaultNamespace('App\Controllers');
$routes->setDefaultController('Home');
$routes->setDefaultMethod('index');
$routes->setTranslateURIDashes(false);
diff --git a/application/Controllers/Home.php b/application/Controllers/Home.php
index 9c5dd52c7d63..85981149e2ed 100644
--- a/application/Controllers/Home.php
+++ b/application/Controllers/Home.php
@@ -1,4 +1,4 @@
-
Date: Tue, 28 Jun 2016 22:44:37 -0500
Subject: [PATCH 0024/1807] Added sample database entries to env.example
---
application/env.example | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/application/env.example b/application/env.example
index 73c2384fa03e..6086d9cc89fc 100644
--- a/application/env.example
+++ b/application/env.example
@@ -39,6 +39,22 @@
# app.CSPEnabled = false
+#--------------------------------------------------------------------
+# DATABASE
+#--------------------------------------------------------------------
+
+# database.default.hostname = localhost
+# database.default.database = ci4
+# database.default.username = root
+# database.default.password = root
+# database.default.DBDriver = MySQLi
+
+# database.tests.hostname = localhost
+# database.tests.database = ci4
+# database.tests.username = root
+# database.tests.password = root
+# database.tests.DBDriver = MySQLi
+
#--------------------------------------------------------------------
# CONTENT SECURITY POLICY
#--------------------------------------------------------------------
From f343fd2fdb444824941a160e9d6555b7b6990577 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 23:02:52 -0500
Subject: [PATCH 0025/1807] Fixing bug with routes and default namespaces.
---
system/CodeIgniter.php | 12 ++++++------
system/Router/RouteCollection.php | 12 ++++++++++++
system/Router/Router.php | 4 +++-
3 files changed, 21 insertions(+), 7 deletions(-)
diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php
index 6edf0b6d8690..0b47f53a9540 100644
--- a/system/CodeIgniter.php
+++ b/system/CodeIgniter.php
@@ -78,21 +78,21 @@ class CodeIgniter
/**
* Current request.
- *
+ *
* @var \CodeIgniter\HTTP\Request
*/
protected $request;
/**
* Current response.
- *
+ *
* @var \CodeIgniter\HTTP\Response
*/
protected $response;
/**
* Router to use.
- *
+ *
* @var \CodeIgniter\Router\Router
*/
protected $router;
@@ -105,7 +105,7 @@ class CodeIgniter
/**
* Controller method to invoke.
- *
+ *
* @var string
*/
protected $method;
@@ -138,7 +138,7 @@ public function __construct(int $startMemory, float $startTime, App $config)
* The class entry point. This is where the magic happens and all
* of the framework pieces are pulled together and shown how to
* make beautiful music together. Or something like that. :)
- *
+ *
* @param RouteCollectionInterface $routes
*/
public function run(RouteCollectionInterface $routes = null)
@@ -216,7 +216,7 @@ public function run(RouteCollectionInterface $routes = null)
/**
* Start the Benchmark
- *
+ *
* The timer is used to display total script execution both in the
* debug toolbar, and potentially on the displayed page.
*/
diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php
index ab56b3f2994e..4302a1c79500 100644
--- a/system/Router/RouteCollection.php
+++ b/system/Router/RouteCollection.php
@@ -373,6 +373,18 @@ public function getDefaultMethod(): string
//--------------------------------------------------------------------
+ /**
+ * Returns the default namespace as set in the Routes config file.
+ *
+ * @return string
+ */
+ public function getDefaultNamespace(): string
+ {
+ return $this->defaultNamespace;
+ }
+
+ //--------------------------------------------------------------------
+
/**
* Returns the current value of the translateURIDashses setting.
*
diff --git a/system/Router/Router.php b/system/Router/Router.php
index 32698c5e6686..076a0b665c5d 100644
--- a/system/Router/Router.php
+++ b/system/Router/Router.php
@@ -139,7 +139,9 @@ public function handle(string $uri = null)
// everything runs off of it's default settings.
if (empty($uri))
{
- return $this->controller;
+ return strpos($this->controller, '\\') === false
+ ? $this->collection->getDefaultNamespace().$this->controller
+ : $this->controller;
}
if ($this->checkRoutes($uri))
From c2649da19784d88dd1849ed9c0c3e15c70b2f1bf Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 23:04:22 -0500
Subject: [PATCH 0026/1807] updated test
---
tests/system/CodeIgniterTest.php | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tests/system/CodeIgniterTest.php b/tests/system/CodeIgniterTest.php
index 47ba2607a695..8bdcddffb99f 100644
--- a/tests/system/CodeIgniterTest.php
+++ b/tests/system/CodeIgniterTest.php
@@ -10,6 +10,8 @@ class CodeIgniterTest extends \CIUnitTestCase
*/
protected $codeigniter;
+ protected $routes;
+
//--------------------------------------------------------------------
public function setUp()
@@ -39,6 +41,9 @@ public function testRunDefaultRoute()
//--------------------------------------------------------------------
+ /**
+ * @group route
+ */
public function testRunEmptyDefaultRoute()
{
$_SERVER['argv'] = [
From e7ace124e858f6005222cac4999ab431a92cc5f8 Mon Sep 17 00:00:00 2001
From: Lonnie Ezell
Date: Tue, 28 Jun 2016 23:42:14 -0500
Subject: [PATCH 0027/1807] Adding note about namespaced views.
---
user_guide_src/source/general/views.rst | 33 +++++++++++++++++--------
1 file changed, 23 insertions(+), 10 deletions(-)
diff --git a/user_guide_src/source/general/views.rst b/user_guide_src/source/general/views.rst
index a368f3cd350f..0091093503a4 100644
--- a/user_guide_src/source/general/views.rst
+++ b/user_guide_src/source/general/views.rst
@@ -35,13 +35,13 @@ To load a particular view file you will use the following function::
view('name');
-Where _name_ is the name of your view file.
+Where _name_ is the name of your view file.
.. important:: The .php file extension does not need to be specified, but all views are expected to end with the .php extension.
Now, open the controller file you made earlier called ``Blog.php``, and replace the echo statement with the view function::
- class Blog extends \CodeIgniter\Controller
+ class Blog extends \CodeIgniter\Controller
{
public function index()
{
@@ -53,6 +53,19 @@ If you visit your site using the URL you did earlier you should see your new vie
example.com/index.php/blog/
+Namespaced Views
+----------------
+
+You can store views under a **View** directory that is namespaced, and load that view as if it was namespaced. While
+PHP does not support loading non-class files from a namespace, CodeIgniter provides this feature to make it possible
+to package your views together in a module-like fashion for easy re-use or distribution.
+
+If you have ``Blog`` directory that has a PSR-4 mapping setup in the :doc:`Autoloader ` living
+under the namespace ``Example\Blog``, you could retrieve view files as if they were namespaced also. Following this
+example, you could load the **BlogView** file from **/blog/views** by prepending the namespace to the view name::
+
+ echo view('Example\Blog\BlogView');
+
Loading Multiple Views
======================
@@ -74,7 +87,7 @@ content view, and a footer view. That might look something like this::
echo view('footer');
}
}
-
+
In the example above, we are using "dynamically added data", which you will see below.
Storing Views within Sub-directories
@@ -96,7 +109,7 @@ Here's an example::
'heading' => 'My Heading',
'message' => 'My Message'
];
-
+
echo view('blogview', $data);
Let's try it with your controller file. Open it and add this code::
@@ -107,11 +120,11 @@ Let's try it with your controller file. Open it and add this code::
{
$data['title'] = "My Real Title";
$data['heading'] = "My Real Heading";
-
+
echo view('blogview', $data);
}
}
-
+
Now open your view file and change the text to variables that correspond to the array keys in your data::
@@ -147,11 +160,11 @@ sets the data, and renders the view. While this is often exactly what you want,
want to work with it more directly. In that case you can access the View service directly::
$renderer = \Config\Services::renderer();
-
+
.. important:: You should create services only within controllers. If you need access to the View class
from a library, you should set that as a dependency in the constructor.
-Then you can use any of the three standard methods that it provides.
+Then you can use any of the three standard methods that it provides.
* **render('view_name', array $options)** Performs the rendering of the view and its data. The $options array is
unused by default, but provided for third-party libraries to use when integrating with different template engines.
@@ -192,11 +205,11 @@ or in an href attribute, you would need different escaping rules to be effective
context as the second parameter. Valid contexts are 'html', 'js', 'css', 'url', and 'attr'::
Some Link
-
+
-
+
+
+***************
+Class Reference
+***************
+
+.. php:interface:: CodeIgniter\\View\\RendererableInterface
+
+ .. php:method:: render($view[, $options[, $saveData=false]]])
+
+ :param string $view: File name of the view source
+ :param array $options: Array of options, as key/value pairs
+ :param boolean $saveData: If true, will save data for use with any other calls, if false, will clean the data after rendering the view.
+ :returns: The rendered text for the chosen view
+ :rtype: string
+
+ Builds the output based upon a file name and any data that has already been set::
+
+ echo $renderer->render('myview');
+
+ Options supported:
+
+ - ``cache`` - the time in seconds, to save a view's results
+ - ``cache_name`` - the ID used to save/retrieve a cached view result; defaults to the viewpath
+ - ``saveData`` - true if the view data parameter should be retained for subsequent calls
+
+
+ .. php:method:: setData([$data[, $context=null]])
+
+ :param array $data: Array of view data strings, as key/value pairs
+ :param string $context: The context to use for data escaping.
+ :returns: The Renderer, for method chaining
+ :rtype: CodeIgniter\\View\\RenderableInterface.
+
+ Sets several pieces of view data at once::
+
+ $renderer->setData(['name'=>'George', 'position'=>'Boss']);
+
+ Supported escape contexts: html, css, js, url.
+ If 'raw', no escaping will happen.
+
+ .. php:method:: setVar($name[, $value=null[, $context=null]])
+
+ :param string $name: Name of the view data variable
+ :param mixed $value: The value of this view data
+ :param string $context: The context to use for data escaping.
+ :returns: The Renderer, for method chaining
+ :rtype: CodeIgniter\\View\\RenderableInterface.
+
+ Sets a single piece of view data::
+
+ $renderer->setVar('name','Joe','html');
+
+ Supported escape contexts: html, css, js, url, or raw.
+ If 'raw', no escaping will happen.
+
diff --git a/user_guide_src/source/general/views.rst b/user_guide_src/source/general/views.rst
index f56a7137962a..6fd9bc2eceaa 100644
--- a/user_guide_src/source/general/views.rst
+++ b/user_guide_src/source/general/views.rst
@@ -18,12 +18,12 @@ Creating a View
Using your text editor, create a file called ``BlogView.php`` and put this in it::
-
- My Blog
-
-
- Welcome to my Blog!
-
+
+ My Blog
+
+
+ Welcome to my Blog!
+
Then save the file in your **application/Views** directory.
@@ -65,7 +65,7 @@ content view, and a footer view. That might look something like this::
public function index()
{
$data = [
- 'page_title' = 'Your title'
+ 'page_title' => 'Your title'
];
echo view('header');
@@ -143,12 +143,12 @@ Let's try it with your controller file. Open it and add this code::
Now open your view file and change the text to variables that correspond to the array keys in your data::
-
- = $title ?>
-
-
- = $heading ?>
-
+
+ = $title ?>
+
+
+ = $heading ?>
+
Then load the page at the URL you've been using and you should see the variables replaced.
@@ -167,70 +167,6 @@ into the `$option` array in the third parameter.
echo view('blogview', $data, ['saveData' => true]);
-Direct Access To View Class
-===========================
-
-The ``view()`` function is a convenience method that grabs an instance of the ``renderer`` service,
-sets the data, and renders the view. While this is often exactly what you want, you may find times where you
-want to work with it more directly. In that case you can access the View service directly::
-
- $renderer = \Config\Services::renderer();
-
-.. important:: You should create services only within controllers. If you need access to the View class
- from a library, you should set that as a dependency in the constructor.
-
-Then you can use any of the three standard methods that it provides.
-
-* **render('view_name', array $options)** Performs the rendering of the view and its data. The $options array is
- unused by default, but provided for third-party libraries to use when integrating with different template engines.
-* **setVar('name', 'value', $context=null)** Sets a single piece of dynamic data. $context specifies the context
- to escape for. Defaults to no escaping. Set to empty value to skip escaping.
-* **setData($array, $context=null)** Takes an array of key/value pairs for dynamic data and optionally escapes it.
- $context specifies the context to escape for. Defaults to no escaping. Set to empty value to skip escaping.
-
-The `setVar()` and `setData()` methods are chainable, allowing you to combine a number of different calls together in a chain::
-
- service('renderer')->setVar('one', $one)
- ->setVar('two', $two)
- ->render('myView');
-
-Escaping Data
-=============
-
-When you pass data to the ``setVar()`` and ``setData()`` functions you have the option to escape the data to protect
-against cross-site scripting attacks. As the last parameter in either method, you can pass the desired context to
-escape the data for. See below for context descriptions.
-
-If you don't want the data to be escaped, you can pass `null` or `raw` as the final parameter to each function::
-
- $renderer->setVar('one', $one, 'raw');
-
-If you choose not to escape data, or you are passing in an object instance, you can manually escape the data within
-the view with the ``esc()`` function. The first parameter is the string to escape. The second parameter is the
-context to escape the data for (see below)::
-
- = esc($object->getStat()) ?>
-
-Escaping Contexts
------------------
-
-By default, the ``esc()`` and, in turn, the ``setVar()`` and ``setData()`` functions assume that the data you want to
-escape is intended to be used within standard HTML. However, if the data is intended for use in Javascript, CSS,
-or in an href attribute, you would need different escaping rules to be effective. You can pass in the name of the
-context as the second parameter. Valid contexts are 'html', 'js', 'css', 'url', and 'attr'::
-
- Some Link
-
-
-
-
-
Creating Loops
==============
@@ -276,70 +212,3 @@ Now open your view file and create a loop::