1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-11 17:24:46 +02:00

Documentation updates to several core classes

This commit is contained in:
Ryan Cramer
2016-11-22 14:26:41 -05:00
parent 3647a47b86
commit c1f4693ca0
13 changed files with 774 additions and 147 deletions

View File

@@ -3,6 +3,10 @@
/**
* ProcessWire Notices
*
* #pw-summary Manages notifications in the ProcessWire admin, primarily for internal use.
* #pw-use-constants
* #pw-use-constructor
*
* Base class that holds a message, source class, and timestamp.
* Contains notices/messages used by the application to the user.
*
@@ -28,6 +32,8 @@ abstract class Notice extends WireData {
/**
* Flag indicates the notice is a warning
*
* #pw-internal
*
* @deprecated use NoticeWarning instead.
*
*/
@@ -46,7 +52,7 @@ abstract class Notice extends WireData {
const logOnly = 16;
/**
* Flag indicates the notice is allowed to contain markup and won't be automatically entity encoded
* Flag indicates the notice is allowed to contain markup and wont be automatically entity encoded
*
* Note: entity encoding is done by the admin theme at output time, which should detect this flag.
*
@@ -56,8 +62,8 @@ abstract class Notice extends WireData {
/**
* Create the Notice
*
* @param string $text
* @param int $flags
* @param string $text Notification text
* @param int $flags Flags
*
*/
public function __construct($text, $flags = 0) {
@@ -69,6 +75,8 @@ abstract class Notice extends WireData {
}
/**
* Get the notice log
*
* @return string Name of log (basename)
*
*/
@@ -111,21 +119,88 @@ class NoticeWarning extends Notice {
/**
* A class to contain multiple Notice instances, whether messages or errors
* ProcessWire Notices
*
* #pw-summary A class to contain multiple Notice instances, whether messages, warnings or errors
* #pw-body =
* This class manages notices that have been sent by `Wire::message()`, `Wire::warning()` and `Wire::error()` calls.
* The message(), warning() and error() methods are available on every `Wire` derived object. This class is primarily
* for internal use in the admin. However, it may also be useful in some front-end contexts.
* ~~~~~
* // Adding a NoticeMessage using object syntax
* $notices->add(new NoticeMessage("Hello World"));
*
* // Adding a NoticeMessage using regular syntax
* $notices->message("Hello World");
*
* // Adding a NoticeWarning, and allow markup in it
* $notices->message("Hello <strong>World</strong>", Notice::allowMarkup);
*
* // Adding a NoticeError that only appears if debug mode is on
* $notices->error("Hello World", Notice::debug);
* ~~~~~
* Iterating and outputting Notices:
* ~~~~~
* foreach($notices as $notice) {
* // skip over debug notices, if debug mode isn't active
* if($notice->flags & Notice::debug && !$config->debug) continue;
* // entity encode notices unless the allowMarkup flag is set
* if($notice->flags & Notice::allowMarkup) {
* $text = $notice->text;
* } else {
* $text = $sanitizer->entities($notice->text);
* }
* // output either an error, warning or message notice
* if($notice instanceof NoticeError) {
* echo "<p class='error'>$text</p>";
* } else if($notice instanceof NoticeWarning) {
* echo "<p class='warning'>$text</p>";
* } else {
* echo "<p class='message'>$text</p>";
* }
* }
* ~~~~~
*
* #pw-body
*
*
*/
class Notices extends WireArray {
const logAllNotices = false; // for debugging/dev purposes
/**
* #pw-internal
*
* @param mixed $item
* @return bool
*
*/
public function isValidItem($item) {
return $item instanceof Notice;
}
}
/**
* #pw-internal
*
* @return Notice
*
*/
public function makeBlankItem() {
return $this->wire(new NoticeMessage(''));
}
/**
* Add a Notice object
*
* ~~~~
* $notices->add(new NoticeError("An error occurred!"));
* ~~~~
*
* @param Notice $item
* @return $this
*
*/
public function add($item) {
if($item->flags & Notice::debug) {
@@ -178,6 +253,12 @@ class Notices extends WireArray {
$this->wire('log')->save($item->getName(), $text);
}
/**
* Are there NoticeError items present?
*
* @return bool
*
*/
public function hasErrors() {
$numErrors = 0;
foreach($this as $notice) {
@@ -185,7 +266,13 @@ class Notices extends WireArray {
}
return $numErrors > 0;
}
/**
* Are there NoticeWarning items present?
*
* @return bool
*
*/
public function hasWarnings() {
$numWarnings = 0;
foreach($this as $notice) {
@@ -199,6 +286,8 @@ class Notices extends WireArray {
*
* This enables us to safely print_r the string for debugging purposes
*
* #pw-internal
*
* @param array $a
* @return array
*

View File

@@ -14,6 +14,11 @@
*
* PageArray is returned by all API methods in ProcessWire that can return more than one page at once.
* `$pages->find()` and `$page->children()` are common examples.
*
* The recommended way to create a new PageArray is to use the `$pages->newPageArray()` method:
* ~~~~~
* $pageArray = $pages->newPageArray();
* ~~~~~
* #pw-body
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer

View File

@@ -7,6 +7,7 @@
* #pw-summary-traversal For the most part youll want to traverse from the parent `Pagefiles` object than these methods.
* #pw-summary-manipulation Remember to follow up any manipulations with a `$pages->save()` call.
* #pw-summary-tags Be sure to see the `Pagefiles::getTag()` and `Pagesfiles::findTag()` methods, which enable you retrieve files by tag.
* #pw-use-constructor
* #pw-body =
* Pagefile objects are contained by a `Pagefiles` object.
* #pw-body
@@ -49,6 +50,8 @@ class Pagefile extends WireData {
/**
* Reference to the owning collection of Pagefiles
*
* @var Pagefiles
*
*/
protected $pagefiles;

View File

@@ -6,6 +6,7 @@
* #pw-summary Represents an image item attached to a page, typically via an Image Fieldtype.
* #pw-summary-variations A variation refers to an image that is based upon another (like a resized or cropped version for example).
* #pw-order-groups common,resize-and-crop,variations,other
* #pw-use-constructor
* #pw-body =
* Pageimage objects are usually contained by a `Pageimages` object, which is a type of `Pagefiles` and `WireArray`.
* In addition to the methods and properties below, you'll also want to look at `Pagefile` which this class inherits
@@ -93,9 +94,14 @@ class Pageimage extends Pagefile {
protected $error = '';
/**
* Construct a new Pagefile
* Construct a new Pageimage
*
* ~~~~~
* // Construct a new Pageimage, assumes that $page->images is a FieldtypeImage Field
* $pageimage = new Pageimage($page->images, '/path/to/file.png');
* ~~~~~
*
* @param Pagefiles $pagefiles
* @param Pageimages|Pagefiles $pagefiles
* @param string $filename Full path and filename to this pagefile
* @throws WireException
*

View File

@@ -3,8 +3,15 @@
/**
* ProcessWire PagesType
*
* Provides an interface to the Pages class but specific to
* a given page class/type, with predefined parent and template.
* #pw-summary Provides an interface to the Pages class but specific to a given page class/type, with predefined parent and template.
* #pw-body =
* This class is primarily used by the core as an alternative to `$pages`, providing an API for other Page types like
* `User`, `Role`, `Permission`, and `Language`. The `$users`, `$roles`, `$permissions` and `$languages` API variables
* are all instances of `PagesType`. This class is typically not instantiated on its own and instead acts as a base class
* which is extended.
*
* #pw-body
* #pw-use-constructor
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
@@ -83,6 +90,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Add one or more templates that this PagesType represents
*
* #pw-group-family
*
* @param array|int|string $templates Single or array of Template objects, IDs, or names
*
*/
@@ -110,6 +119,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Add one or more of parents that this PagesType represents
*
* #pw-group-family
*
* @param array|int|string|Page $parents Single or array of Page objects, IDs, or paths
*
*/
@@ -170,6 +181,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Is the given page a valid type for this class?
*
* #pw-internal
*
* @param Page $page
* @return bool
@@ -233,9 +246,10 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
* Given a Selector string, return the Page objects that match in a PageArray.
*
* @param string $selectorString
* @param array $options
- findOne: apply optimizations for finding a single page and include pages with 'hidden' status
* @param array $options Options to modify default behavior:
* - `findOne` (bool): apply optimizations for finding a single page and include pages with 'hidden' status
* @return PageArray
* @see Pages::find()
*
*/
public function find($selectorString, $options = array()) {
@@ -301,13 +315,11 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
}
/**
* Save a page object and it's fields to database.
* Save a page object and its fields to database.
*
* If the page is new, it will be inserted. If existing, it will be updated.
*
* This is the same as calling $page->save()
*
* If you want to just save a particular field in a Page, use $page->save($fieldName) instead.
* - This is the same as calling $page->save()
* - If the page is new, it will be inserted. If existing, it will be updated.
* - If you want to just save a particular field in a Page, use `$page->save($fieldName)` instead.
*
* @param Page $page
* @return bool True on success
@@ -320,11 +332,11 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
}
/**
* Permanently delete a page and it's fields.
* Permanently delete a page and its fields.
*
* Unlike trash(), pages deleted here are not restorable.
* Unlike `$pages->trash()`, pages deleted here are not restorable.
*
* If you attempt to delete a page with children, and don't specifically set the $recursive param to True, then
* If you attempt to delete a page with children, and dont specifically set the `$recursive` argument to `true`, then
* this method will throw an exception. If a recursive delete fails for any reason, an exception will be thrown.
*
* @param Page $page
@@ -339,12 +351,12 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
}
/**
* Adds a new page with the given $name and returns the Page
* Adds a new page with the given $name and returns it
*
* If they page has any other fields, they will not be populated, only the name will.
* Returns a NullPage if error, such as a page of this type already existing with the same name.
* - If the page has any other fields, they will not be populated, only the name will.
* - Returns a `NullPage` on error, such as when a page of this type already exists with the same name/parent.
*
* @param string $name
* @param string $name Name to use for the new page
* @return Page|NullPage
*
*/
@@ -375,32 +387,82 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
* Make it possible to iterate all pages of this type per the \IteratorAggregate interface.
*
* Only recommended for page types that don't contain a lot of pages.
*
* #pw-internal
*
*/
public function getIterator() {
return $this->find("id>0, sort=name");
}
}
/**
* Get the template used by this type (or first template if there are multiple)
*
* #pw-group-family
*
* @return Template
*
*/
public function getTemplate() {
return $this->template;
}
/**
* Get the templates (plural) used by this type
*
* #pw-group-family
*
* @return array|Template[] Array of Template objects indexed by template ID.
*
*/
public function getTemplates() {
return count($this->templates) ? $this->templates : array($this->template);
}
/**
* Get the parent page ID used by this type (or first parent ID if there are multiple)
*
* #pw-group-family
*
* @return int
*
*/
public function getParentID() {
return $this->parent_id;
}
/**
* Get the parent page IDs used by this type
*
* #pw-group-family
*
* @return array Array of parent page IDs (integers)
*
*/
public function getParentIDs() {
return count($this->parents) ? $this->parents : array($this->parent_id);
}
/**
* Get the parent Page object (or first parent Page object if there are multiple)
*
* #pw-group-family
*
* @return Page|NullPage
*
*/
public function getParent() {
return $this->wire('pages')->get($this->parent_id);
}
/**
* Get the parent Page objects in a PageArray
*
* #pw-group-family
*
* @return PageArray
*
*/
public function getParents() {
if(count($this->parents)) {
return $this->wire('pages')->getById($this->parents);
@@ -411,17 +473,42 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
return $parents;
}
}
/**
* Set the PHP class name to use for Page objects of this type
*
* #pw-group-family
*
* @param string $class
*
*/
public function setPageClass($class) {
$this->pageClass = $class;
}
/**
* Get the PHP class name used by Page objects of this type
*
* #pw-group-family
*
* @return string
*
*/
public function getPageClass() {
if($this->pageClass) return $this->pageClass;
if($this->template && $this->template->pageClass) return $this->template->pageClass;
return 'Page';
}
/**
* Return the number of pages in this type matching the given selector string
*
* @param string $selectorString Optional, if omitted then returns count of all pages of this type
* @param array $options Options to modify default behavior (see $pages->count method for details)
* @return int
* @see Pages::count()
*
*/
public function count($selectorString = '', array $options = array()) {
if(empty($selectorString) && empty($options) && count($this->parents) == 1) {
return $this->getParent()->numChildren();
@@ -449,6 +536,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Hook called just before a page is saved
*
* #pw-hooker
*
* @param Page $page The page about to be saved
* @return array Optional extra data to add to pages save query.
@@ -464,6 +553,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
*
* This is the same as Pages::save, except that it occurs before other save-related hooks (below),
* Whereas Pages::save occurs after. In most cases, the distinction does not matter.
*
* #pw-hooker
*
* @param Page $page The page that was saved
* @param array $changes Array of field names that changed
@@ -474,6 +565,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Hook called when a new page has been added
*
* #pw-hooker
*
* @param Page $page
*
@@ -482,6 +575,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Hook called when a page is about to be deleted, but before data has been touched
*
* #pw-hooker
*
* @param Page $page
*
@@ -490,6 +585,8 @@ class PagesType extends Wire implements \IteratorAggregate, \Countable {
/**
* Hook called when a page and it's data have been deleted
*
* #pw-hooker
*
* @param Page $page
*

View File

@@ -1,45 +1,105 @@
<?php namespace ProcessWire;
/**
* ProcessWire API Bootstrap
*
* Initializes all the ProcessWire classes and prepares them for API use
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
* @todo: get language permissions to work with extra actions
*
*/
require_once(__DIR__ . '/boot.php');
/**
* ProcessWire API bootstrap class
* ProcessWire API Bootstrap
*
* Gets ProcessWire's API ready for use
* #pw-summary Represents an instance of ProcessWire connected with a set of API variables.
* #pw-summary-instances Methods for managing ProcessWire instances. Note that most of these methods are static.
* #pw-use-constants
* #pw-use-constructor
* #pw-body =
* This class boots a ProcessWire instance. The current ProcessWire instance is represented by the `$wire` API variable.
* ~~~~~
* // To create a new ProcessWire instance
* $wire = new ProcessWire('/server/path/', 'https://hostname/url/');
* ~~~~~
* #pw-body
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
* @method init()
* @method ready()
* @method finished()
*
*/
*
*
*/
class ProcessWire extends Wire {
const versionMajor = 3;
const versionMinor = 0;
const versionRevision = 41;
/**
* Major version number
*
*/
const versionMajor = 3;
/**
* Minor version number
*
*/
const versionMinor = 0;
/**
* Reversion revision number
*
*/
const versionRevision = 41;
/**
* Version suffix string (when applicable)
*
*/
const versionSuffix = '';
const indexVersion = 300; // required version for index.php file (represented by PROCESSWIRE define)
/**
* Minimum required index.php version, represented by the PROCESSWIRE define
*
*/
const indexVersion = 300;
/**
* Minimum required .htaccess file version
*
*/
const htaccessVersion = 300;
const statusBoot = 0; // system is booting
const statusInit = 2; // system and modules are initializing
const statusReady = 4; // system and $page are ready
const statusRender = 8; // $page's template is being rendered
const statusFinished = 16; // request has been delivered
const statusFailed = 1024; // request failed due to exception or 404
/**
* Status when system is booting
*
*/
const statusBoot = 0;
/**
* Status when system and modules are initializing
*
*/
const statusInit = 2;
/**
* Systus when system, $page and API variables are ready
*
*/
const statusReady = 4;
/**
* Status when the current $pages template file is being rendered
*
*/
const statusRender = 8;
/**
* Status when the request has been fully delivered
*
*/
const statusFinished = 16;
/**
* Status when the request failed due to an Exception or 404
*
*/
const statusFailed = 1024;
/**
* Whether debug mode is on or off
@@ -126,7 +186,7 @@ class ProcessWire extends Wire {
if(is_string($config)) $config = self::buildConfig($config, $rootURL);
if(!$config instanceof Config) throw new WireException("No configuration information available");
// this is reset in the $this->config() method based on current debug mode
// this is reset in the $this->setConfig() method based on current debug mode
ini_set('display_errors', true);
error_reporting(E_ALL | E_STRICT);
@@ -145,7 +205,7 @@ class ProcessWire extends Wire {
$this->wire('hooks', new WireHooks($this, $config), true);
$this->shutdown = $this->wire(new WireShutdown());
$this->config($config);
$this->setConfig($config);
$this->load($config);
if($this->getNumInstances() > 1) {
@@ -170,7 +230,7 @@ class ProcessWire extends Wire {
* @param Config $config
*
*/
protected function config(Config $config) {
protected function setConfig(Config $config) {
$this->wire('config', $config, true);
$this->wire($config->paths);
@@ -277,7 +337,9 @@ class ProcessWire extends Wire {
}
/**
* Load's ProcessWire using the supplied Config and populates all API fuel
* Loads ProcessWire using the supplied Config and populates all API fuel
*
* #pw-internal
*
* @param Config $config
* @throws WireDatabaseException|WireException on fatal error
@@ -417,6 +479,8 @@ class ProcessWire extends Wire {
/**
* Hookable init for anyone that wants to hook immediately before any autoload modules initialized or after all modules initialized
*
* #pw-hooker
*
*/
protected function ___init() {
if($this->debug) Debug::timer('boot.modules.autoload.init');
@@ -426,6 +490,8 @@ class ProcessWire extends Wire {
/**
* Hookable ready for anyone that wants to hook immediately before any autoload modules ready or after all modules ready
*
* #pw-hooker
*
*/
protected function ___ready() {
@@ -438,6 +504,8 @@ class ProcessWire extends Wire {
/**
* Hookable ready for anyone that wants to hook when the request is finished
*
* #pw-hooker
*
*/
protected function ___finished() {
@@ -513,7 +581,16 @@ class ProcessWire extends Wire {
if(is_object($value)) return call_user_func_array(array($value, '__invoke'), $arguments);
return parent::__call($method, $arguments);
}
/**
* Get an API variable
*
* #pw-internal
*
* @param string $name Optional API variable name
* @return mixed|null|Fuel
*
*/
public function fuel($name = '') {
if(empty($name)) return $this->fuel;
return $this->fuel->$name;
@@ -540,6 +617,8 @@ class ProcessWire extends Wire {
/**
* Instance ID of this ProcessWire instance
*
* #pw-group-instances
*
* @return int
*
*/
@@ -550,6 +629,8 @@ class ProcessWire extends Wire {
/**
* Add a ProcessWire instance and return the instance ID
*
* #pw-group-instances
*
* @param ProcessWire $wire
* @return int
*
@@ -564,6 +645,8 @@ class ProcessWire extends Wire {
/**
* Get all ProcessWire instances
*
* #pw-group-instances
*
* @return array
*
*/
@@ -574,6 +657,8 @@ class ProcessWire extends Wire {
/**
* Return number of instances
*
* #pw-group-instances
*
* @return int
*
*/
@@ -584,6 +669,8 @@ class ProcessWire extends Wire {
/**
* Get a ProcessWire instance by ID
*
* #pw-group-instances
*
* @param int|null $instanceID Omit this argument to return the current instance
* @return null|ProcessWire
*
@@ -596,6 +683,8 @@ class ProcessWire extends Wire {
/**
* Get the current ProcessWire instance
*
* #pw-group-instances
*
* @return ProcessWire|null
*
*/
@@ -610,6 +699,8 @@ class ProcessWire extends Wire {
/**
* Set the current ProcessWire instance
*
* #pw-group-instances
*
* @param ProcessWire $wire
*
*/
@@ -620,6 +711,8 @@ class ProcessWire extends Wire {
/**
* Remove a ProcessWire instance
*
* #pw-group-instances
*
* @param ProcessWire $wire
*
*/
@@ -634,7 +727,7 @@ class ProcessWire extends Wire {
}
/**
* Build a Config object for booting ProcessWire
* Static method to build a Config object for booting ProcessWire
*
* @param string $rootPath Path to root of installation where ProcessWire's index.php file is located.
* @param string $rootURL Should be specified only for secondary ProcessWire instances.

View File

@@ -11,33 +11,62 @@
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
*/
/**
* Selector maintains a single selector consisting of field name, operator, and value.
*
* Field and value may optionally be arrays, where are assumed to be OR values.
* #pw-summary Selector maintains a single selector consisting of field name, operator, and value.
*
* Serves as the base class for the different Selector types (seen below this class).
* #pw-body =
* - Serves as the base class for the different Selector types (`SelectorEqual`, `SelectorNotEqual`, `SelectorLessThan`, etc.)
* - The constructor requires `$field` and `$value` properties which may either be an array or string.
* An array indicates multiple items in an OR condition. Multiple items may also be specified by
* pipe “|” separated strings.
* - Operator is determined by the Selector class name, and thus may not be changed without replacing
* the entire Selector.
*
* @property string|array $field Field or fields present in the selector (can be string or array) [1]
* @property array $fields Fields that were present in selector (same as $field, but always array)
* @property string $operator Operator used by the selector [2]
* @property string|array $value Value or values present in the selector (can be string or array) [1]
* @property array $values Values that were present in selector (same as $value, but always array)
* @property bool $not Is this a NOT selector? (i.e. returns the opposite if what it would otherwise)
* @property string|null $group Group name for this selector (if field was prepended with a "group_name@")
* @property string $quote Type of quotes value was in, or blank if it was not quoted. One of: '"[{(
* @property string $str String value of selector
* @property null|bool $forceMatch When boolean, it forces match (true) or non-match (false).
* ~~~~~
* // very basic usage example
* // constructor takes ($field, $value) which can be strings or arrays
* $s = new SelectorEqual('title', 'About Us');
* // $page can be any kind of Wire-derived object
* if($s->matches($page)) {
* // $page has title "About Us"
* }
* ~~~~~
* ~~~~~
* // another usage example
* $s = new SelectorContains('title|body|summary', 'foo|bar');
* if($s->matches($page)) {
* // the title, body or summary properties of $page contain either the text "foo" or "bar"
* }
* ~~~~~
*
* [1] The $field and $value properties may either be an array or string. As a result, we recommend
* accessing the $fields or $values properties (instead of $field or $value), because they are always
* return an array.
* ### List of core selector-derived classes
*
* [2] Operator is determined by the Selector class name, and thus may not be changed without replacing
* the entire Selector.
* - `SelectorEqual`
* - `SelectorNotEqual`
* - `SelectorGreaterThan`
* - `SelectorLessThan`
* - `SelectorGreaterThanEqual`
* - `SelectorLessThanEqual`
* - `SelectorContains`
* - `SelectorContainsLike`
* - `SelectorContainsWords`
* - `SelectorStarts`
* - `SelectorStartsLike`
* - `SelectorEnds`
* - `SelectorEndsLike`
* - `SelectorBitwiseAnd`
*
* #pw-body
*
* @property array $fields Fields that were present in selector (same as $field, but always an array).
* @property string|array $field Field or fields present in the selector (string if single, or array of strings if multiple). Preferable to use $fields property instead.
* @property-read string $operator Operator used by the selector.
* @property array $values Values that were present in selector (same as $value, but always array).
* @property string|array $value Value or values present in the selector (string if single, or array of strings if multiple). Preferable to use $values property instead.
* @property bool $not Is this a NOT selector? Indicates the selector returns the opposite if what it would otherwise. #pw-group-properties
* @property string|null $group Group name for this selector (if field was prepended with a "group_name@"). #pw-group-properties
* @property string $quote Type of quotes value was in, or blank if it was not quoted. One of: '"[{( #pw-group-properties
* @property-read string $str String value of selector, i.e. “a=b”. #pw-group-properties
* @property null|bool $forceMatch When boolean, it forces match (true) or non-match (false). (default=null) #pw-group-properties
*
*/
abstract class Selector extends WireData {
@@ -71,27 +100,112 @@ abstract class Selector extends WireData {
$this->set('forceMatch', null); // boolean true to force match, false to force non-match
}
/**
* Return the operator used by this Selector
*
* @return string
* @since 3.0.42 Prior versions just supported the 'operator' property.
*
*/
public function operator() {
return self::getOperator();
}
/**
* Get the field(s) of this Selector
*
* Note that if calling this as a property (rather than a method) it can return either a string or an array.
*
* @param bool|int $forceString Specify one of the following:
* - `true` (bool): to only return a string, where multiple-fields will be split by pipe "|". (default)
* - `false` (bool): to return string if 1 field, or array of multiple fields (same behavior as field property).
* - `1` (int): to return only the first value (string).
* @return string|array|null
* @since 3.0.42 Prior versions only supported the 'field' property.
* @see Selector::fields()
*
*/
public function field($forceString = true) {
$field = parent::get('field');
if($forceString && is_array($field)) {
if($forceString === 1) {
$field = reset($field);
} else {
$field = implode('|', $field);
}
}
return $field;
}
/**
* Return array of field(s) for this Selector
*
* @return array
* @see Selector::field()
* @since 3.0.42 Prior versions just supported the 'fields' property.
*
*/
public function fields() {
$field = parent::get('field');
if(is_array($field)) return $field;
if(!strlen($field)) return array();
return array($field);
}
/**
* Get the value(s) of this Selector
*
* Note that if calling this as a property (rather than a method) it can return either a string or an array.
*
* @param bool|int $forceString Specify one of the following:
* - `true` (bool): to only return a string, where multiple-values will be split by pipe "|". (default)
* - `false` (bool): to return string if 1 value, or array of multiple values (same behavior as value property).
* - `1` (int): to return only the first value (string).
* @return string|array|null
* @since 3.0.42 Prior versions only supported the 'value' property.
* @see Selector::values()
*
*/
public function value($forceString = true) {
$value = parent::get('value');
if($forceString && is_array($value)) {
if($forceString === 1) {
$value = reset($value);
} else {
$value = implode('|', $value);
}
}
return $value;
}
/**
* Return array of value(s) for this Selector
*
* @return array
* @see Selector::value()
* @since 3.0.42 Prior versions just supported the 'values' property.
*
*/
public function values() {
$values = parent::get('value');
if(is_array($values)) return $values;
if(!is_object($values) && !strlen($values)) return array();
return array($values);
}
public function get($key) {
if($key == 'operator') return $this->getOperator();
if($key == 'str') return $this->__toString();
if($key == 'values') {
$value = $this->value;
if(is_array($value)) return $value;
if(!is_object($value) && !strlen($value)) return array();
return array($value);
}
if($key == 'fields') {
$field = $this->field;
if(is_array($field)) return $field;
if(!strlen($field)) return array();
return array($field);
}
if($key == 'values') return $this->values();
if($key == 'fields') return $this->fields();
return parent::get($key);
}
/**
* Returns the selector field(s), optionally forcing as string or array
*
* #pw-internal
*
* @param string $type Omit for automatic, or specify 'string' or 'array' to force return in that type
* @return string|array
* @throws WireException if given invalid type
@@ -115,6 +229,8 @@ abstract class Selector extends WireData {
* When the $type argument is not specified, this method may return a string, array or Selectors object.
* A Selectors object is only returned if the value happens to contain an embedded selector.
*
* #pw-internal
*
* @param string $type Omit for automatic, or specify 'string' or 'array' to force return in that type
* @return string|array|Selectors
* @throws WireException if given invalid type
@@ -160,6 +276,8 @@ abstract class Selector extends WireData {
* Return the operator used by this Selector
*
* Strict standards don't let us make static abstract methods, so this one throws an exception if it's not reimplemented.
*
* #pw-internal
*
* @return string
* @throws WireException
@@ -291,6 +409,8 @@ abstract class Selector extends WireData {
/**
* Add all individual selector types to the runtime Selectors
*
* #pw-internal
*
*/
static public function loadSelectorTypes() {

View File

@@ -1,17 +1,40 @@
<?php namespace ProcessWire;
require_once(PROCESSWIRE_CORE_PATH . "Selector.php");
/**
* ProcessWire Selectors
*
* Processes a Selector string and can then be iterated to retrieve each resulting Selector object.
* #pw-summary Processes a selector string into a WireArray of Selector objects.
* #pw-summary-static-helpers Static helper methods useful in analyzing selector strings outside of this class.
* #pw-body =
* This Selectors class is used internally by ProcessWire to provide selector string (and array) matching throughout the core.
*
* ~~~~~
* $selectors = new Selectors("sale_price|retail_price>100, currency=USD|EUR");
* if($selectors->matches($page)) {
* // selector string matches the given $page (which can be any Wire-derived item)
* }
* ~~~~~
* ~~~~~
* // iterate and display what's in this Selectors object
* foreach($selectors as $selector) {
* echo "<p>";
* echo "Field(s): " . implode('|', $selector->fields) . "<br>";
* echo "Operator: " . $selector->operator . "<br>";
* echo "Value(s): " . implode('|', $selector->values) . "<br>";
* echo "</p>";
* }
* ~~~~~
* #pw-body
*
* @link https://processwire.com/api/selectors/ Official Selectors Documentation
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
*/
require_once(PROCESSWIRE_CORE_PATH . "Selector.php");
class Selectors extends WireArray {
/**
@@ -104,6 +127,11 @@ class Selectors extends WireArray {
/**
* Set the selector string or array (if not set already from the constructor)
*
* ~~~~~
* $selectors = new Selectors();
* $selectors->init("sale_price|retail_price>100, currency=USD|EUR");
* ~~~~~
*
* @param string|array $selector
*
*/
@@ -120,6 +148,8 @@ class Selectors extends WireArray {
/**
* Set the selector string
*
* #pw-internal
*
* @param string $selectorStr
*
*/
@@ -131,6 +161,8 @@ class Selectors extends WireArray {
/**
* Import items into this WireArray.
*
* #pw-internal
*
* @throws WireException
* @param string|WireArray $items Items to import.
* @return WireArray This instance.
@@ -148,6 +180,8 @@ class Selectors extends WireArray {
/**
* Per WireArray interface, return true if the item is a Selector instance
*
* #pw-internal
*
* @param Selector $item
* @return bool
*
@@ -158,6 +192,8 @@ class Selectors extends WireArray {
/**
* Per WireArray interface, return a blank Selector
*
* #pw-internal
*
*/
public function makeBlankItem() {
@@ -169,6 +205,8 @@ class Selectors extends WireArray {
*
* Static since there may be multiple instances of this Selectors class at runtime.
* See Selector.php
*
* #pw-internal
*
* @param string $operator
* @param string $class
@@ -184,6 +222,10 @@ class Selectors extends WireArray {
/**
* Return array of all valid operator characters
*
* #pw-group-static-helpers
*
* @return array
*
*/
static public function getOperatorChars() {
@@ -192,6 +234,8 @@ class Selectors extends WireArray {
/**
* Does the given string have an operator in it?
*
* #pw-group-static-helpers
*
* @param string $str
* @return bool
@@ -250,6 +294,8 @@ class Selectors extends WireArray {
* Does the given string start with a selector?
*
* Meaning string starts with [field][operator] like "field="
*
* #pw-group-static-helpers
*
* @param string $str
* @return bool
@@ -283,14 +329,18 @@ class Selectors extends WireArray {
return $has;
}
/**
* Create a new Selector object from a field name, operator, and value
*
* This is mostly for internal use, as the Selectors object already does this when you pass it
* a selector string in the constructor or init() method.
*
* #pw-group-advanced
*
* @param string $field
* @param string $operator
* @param string $value
* @return Selector
* @param string $field Field name or names (separated by a pipe)
* @param string $operator Operator, i.e. "="
* @param string $value Value or values (separated by a pipe)
* @return Selector Returns the correct type of `Selector` object that corresponds to the given `$operator`.
* @throws WireException
*
*/
@@ -613,6 +663,8 @@ class Selectors extends WireArray {
/**
* Given a value string with an "api_var" or "api_var.property" return the string value of the property
*
* #pw-internal
*
* @param string $value var or var.property
* @return null|string Returns null if it doesn't resolve to anything or a string of the value it resolves to
@@ -634,6 +686,8 @@ class Selectors extends WireArray {
* Set whether or not vars should be parsed
*
* By default this is true, so only need to call this method to disable variable parsing.
*
* #pw-internal
*
* @param bool $parseVars
*
@@ -645,6 +699,8 @@ class Selectors extends WireArray {
/**
* Does the given Selector value contain a parseable value?
*
* #pw-internal
*
* @param Selector $selector
* @return bool
*
@@ -665,6 +721,8 @@ class Selectors extends WireArray {
* Does the given value contain an API var reference?
*
* It is assumed the value was quoted in "[value]", and the quotes are not there now.
*
* #pw-internal
*
* @param string $value The value to evaluate
* @return bool
@@ -757,6 +815,8 @@ class Selectors extends WireArray {
/**
* Create this Selectors object from an array
*
* #pw-internal
*
* @param array $a
* @throws WireException
@@ -883,6 +943,7 @@ class Selectors extends WireArray {
if(isset($data['value'])) throw new WireException("You may not specify both 'value' and 'find' at the same time");
// if(!is_array($data['find'])) throw new WireException("Selector 'find' property must be specified as array");
$find = $data['find'];
$data['value'] = array();
}
if(isset($data['whitelist']) && $data['whitelist'] !== null) {
@@ -967,6 +1028,14 @@ class Selectors extends WireArray {
$fields[] = $_name;
}
// convert WireArray types to an array of $_values
if(count($_values) === 1) {
$value = reset($_values);
if(is_object($value) && $value instanceof WireArray) {
$_values = explode('|', (string) $value);
}
}
// determine value(s)
foreach($_values as $value) {
$_sanitize = $sanitize;
@@ -1017,6 +1086,8 @@ class Selectors extends WireArray {
* - If you need a literal comma, use a double comma ",,".
* - If you need a literal equals, use a double equals "==".
*
* #pw-group-static-helpers
*
* @param string $s
* @return array
*
@@ -1052,6 +1123,8 @@ class Selectors extends WireArray {
/**
* Given an assoc array, convert to a key=value selector-style string
*
* #pw-group-static-helpers
*
* @param $a
* @return string
*

View File

@@ -28,7 +28,7 @@
* @method void loginFailure($name, $reason) #pw-hooker
* @method void logoutSuccess(User $user) #pw-hooker
*
* @property SessionCSRF $CSRF
* @property SessionCSRF $CSRF
*
* Expected $config variables include:
* ===================================
@@ -395,9 +395,7 @@ class Session extends Wire implements \IteratorAggregate {
*/
public function get($key, $_key = null) {
if($key == 'CSRF') {
if(!$this->sessionInit) $this->init(); // init required for CSRF
if(is_null($this->CSRF)) $this->CSRF = $this->wire(new SessionCSRF());
return $this->CSRF;
return $this->CSRF();
} else if(!is_null($_key)) {
// namespace
return $this->getFor($key, $_key);
@@ -1133,4 +1131,32 @@ class Session extends Wire implements \IteratorAggregate {
}
}
/**
* Return an instance of ProcessWires CSRF object, which provides an API for cross site request forgery protection.
*
* ~~~~
* // output somewhere in <form> markup when rendering a form
* echo $session->CSRF->renderInput();
* ~~~~
* ~~~~
* // when processing form (POST request), check to see if token is present
* if($session->CSRF->hasValidToken()) {
* // form submission is valid
* // okay to process
* } else {
* // form submission is NOT valid
* throw new WireException('CSRF check failed!');
* }
* ~~~~
*
* @return SessionCSRF
* @see SessionCSRF::renderInput(), SessionCSRF::validate(), SessionCSRF::hasValidToken()
*
*/
public function CSRF() {
if(!$this->sessionInit) $this->init(); // init required for CSRF
if(is_null($this->CSRF)) $this->CSRF = $this->wire(new SessionCSRF());
return $this->CSRF;
}
}

View File

@@ -2,26 +2,52 @@
/**
* ProcessWire CSRF Protection
*
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
*/
/**
* Triggered when CSRF detected
* Exception triggered by SessionCSRF::validate() when CSRF detected
*
*/
class WireCSRFException extends WireException {}
/**
* ProcessWire CSRF Protection class
* ProcessWire CSRF Protection
*
* #pw-summary Provides an API for cross site request forgery protection.
* #pw-body =
* ~~~~
* // output somewhere in form markup when rendering a form
* echo $session->CSRF->renderInput();
* ~~~~
* ~~~~
* // when processing form (POST request), check to see if token is present
* if($session->CSRF->hasValidToken()) {
* // form submission is valid
* // okay to process
* } else {
* // form submission is NOT valid
* throw new WireException('CSRF check failed!');
* }
* ~~~~
* ~~~~
* // this alternative to hasValidToken() throws WireCSRFException when invalid
* $session->CSRF->validate();
* ~~~~
*
* #pw-body
*
*
*/
class SessionCSRF extends Wire {
/**
* Get a CSRF Token name, or create one if it doesn't yet exist
*
* #pw-group-initiating
*
* @param int|string|null $id Optional unique ID for this token
* @return string
@@ -38,6 +64,8 @@ class SessionCSRF extends Wire {
/**
* Get a CSRF Token value as stored in the session, or create one if it doesn't yet exist
*
* #pw-group-initiating
*
* @param int|string|null $id Optional unique ID for this token
* @return string
@@ -57,6 +85,8 @@ class SessionCSRF extends Wire {
/**
* Get a CSRF Token timestamp
*
* #pw-group-initiating
*
* @param int|string|null $id Optional unique ID for this token
* @return string
@@ -70,6 +100,8 @@ class SessionCSRF extends Wire {
/**
* Get a CSRF Token name and value
*
* #pw-group-initiating
*
* @param int|string|null $id Optional unique ID for this token
* @return array ("name" => "token name", "value" => "token value", "time" => created timestamp)
@@ -87,7 +119,9 @@ class SessionCSRF extends Wire {
* Get a CSRF Token name and value that can only be used once
*
* Note that a single call to hasValidToken($id) or validate($id) will invalidate the single use token.
* So call them once and store your result if you need the result multiple times.
* So call them once and store your result if you need the result multiple times.
*
* #pw-group-initiating
*
* @param int|string $id Optional unique ID/name for this token (of omitted one is generated automatically)
* @return array ("id' => "token ID", "name" => "token name", "value" => "token value", "time" => created timestamp)
@@ -111,6 +145,8 @@ class SessionCSRF extends Wire {
/**
* Returns true if the current POST request contains a valid CSRF token, false if not
*
* #pw-group-validating
*
* @param int|string|null $id Optional unique ID for this token, but required if checking a single use token.
* @return bool
@@ -139,6 +175,8 @@ class SessionCSRF extends Wire {
/**
* Throws an exception if the token is invalid
*
* #pw-group-validating
*
* @param int|string|null $id Optional unique ID for this token
* @throws WireCSRFException if token not valid
@@ -154,6 +192,8 @@ class SessionCSRF extends Wire {
/**
* Clear out token value
*
* #pw-group-resetting
*
* @param int|string|null $id Optional unique ID for this token
*
@@ -166,6 +206,8 @@ class SessionCSRF extends Wire {
/**
* Clear out all saved token values
*
* #pw-group-resetting
*
*/
public function resetAll() {
@@ -174,6 +216,15 @@ class SessionCSRF extends Wire {
/**
* Render a form input[hidden] containing the token name and value, as looked for by hasValidToken()
*
* ~~~~~
* <form method='post'>
* <input type='submit'>
* <?php echo $session->CSRF->renderInput(); ?>
* </form>
* ~~~~~
*
* #pw-group-initiating
*
* @param int|string|null $id Optional unique ID for this token
* @return string

View File

@@ -1,35 +1,63 @@
<?php namespace ProcessWire;
/**
* ProcessWire Database Backup and Restore
*
* #pw-summary ProcessWire Database Backup and Restore
* #pw-body =
* This class intentionally does not have any external dependencies (other than PDO)
* so that it can be included by outside tools for restoring/exporting, with the main
* example of that being the ProcessWire installer.
*
* The recommended way to access these backup methods is via the `$database` API variable
* method `$database->backups()`, which returns a `WireDatabaseBackup` instance.
*
* ### Easy Initialization (recommended)
* ~~~~~
* $backup = $database->backups();
* ~~~~~
*
* ### Manual Initialization (if you need it)
* ~~~~~
* // determine where backups will go (should NOT be web accessible)
* $backupPath = $config->paths->assets . 'backups/';
*
* // create a new WireDatabaseBackup instance
* $backup = new WireDatabaseBackup($backupPath);
*
* // Option 1: set the already-connected DB connection
* $backup->setDatabase($this->database);
*
* // Option 2: OR provide a Config object that contains the DB connection info
* $backup->setDatabaseConfig($this->config);
*
* ~~~~~
* ### Backup the database
* ~~~~~
* $options = array(); // optional
* $file = $backup->backup($options);
* if($file) {
* print_r($backup->notes());
* } else {
* print_r($backup->errors());
* }
* ~~~~~
* Note: the `print_r()` function calls are just for demonstration and testing purposes. We are not suggesting
* you actually do that except when testing.
*
* ### Restore a database
* ~~~~~
* $options = array(); // optional
* $success = $backup->restore($file, $options);
* if($success) {
* print_r($backup->notes());
* } else {
* print_r($backup->errors());
* }
* ~~~~~
* #pw-body
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* https://processwire.com
*
* USAGE
*
* Initialization
* ==============
* $backup = new WireDatabaseBackup('/path/to/backups/');
* $backup->setDatabase($this->database); // optional, if omitted it will attempt it's own connection
* $backup->setDatabaseConfig($this->config); // optional, only if setDatabase() was called
*
* Backup
* ======
* $file = $backup->backup([$options]);
* if($file) print_r($backup->notes());
* else print_r($backup->errors());
*
*
* Restore
* =======
* $success = $backup->restore($file, [$options]);
* if($success) print_r($backup->notes());
* else print_r($backup->errors());
*
*/
@@ -548,9 +576,26 @@ class WireDatabaseBackup {
/**
* Perform a database export/dump
*
* @param array $options See $backupOptions
* @return string Full path and filename of database export file, or false on failure.
* @param array $options Options to modify default behavior:
* - `filename` (string): filename for backup: default is to make a dated filename, but this can also be used (basename only, no path)
* - `description` (string): optional description of this backup
* - `tables` (array): if specified, export will only include these tables
* - `user` (string): username to associate with the backup file (string), optional
* - `excludeTables` (array): exclude creating or inserting into these tables
* - `excludeCreateTables` (array): exclude creating these tables, but still export data
* - `excludeExportTables` (array): exclude exporting data, but still create tables
* - `whereSQL` (array): SQL conditions for export of individual tables [table => [SQL conditions]]. The `table` portion (index) may also be a full PCRE regexp, must start with `/` to be recognized as regex.
* - `maxSeconds` (int): max number of seconds allowed for execution (default=1200)
* - `allowDrop` (bool): use DROP TABLES statements before CREATE TABLE statements? (default=true)
* - `allowUpdate` (bool): use UPDATE ON DUPLICATE KEY so that INSERT statements can UPDATE when rows already present (all tables). (default=false)
* - `allowUpdateTables` (array): table names that will use UPDATE ON DUPLICATE KEY (does NOT require allowUpdate=true)
* - `findReplace` (array): find and replace in row data during backup. Example: ['databass' => 'database']
* - `findReplaceCreateTable` (array): find and replace in create table statements
* Example: ['DEFAULT CHARSET=latin1;' => 'DEFAULT CHARSET=utf8;']
* - `extraSQL` (array): additional SQL queries to append at the bottom. Example: ['UPDATE pages SET created=NOW()']
* @return string Full path and filename of database export file, or false on failure.
* @throws \Exception on fatal error
* @see WireDatabaseBackup::restore()
*
*/
public function backup(array $options = array()) {
@@ -827,9 +872,17 @@ class WireDatabaseBackup {
* Import a database SQL file that was created by this class
*
* @param string $filename Filename to restore, optionally including path (if no path, then path set to construct is assumed)
* @param array $options See WireDatabaseBackup::$restoreOptions
* @param array $options Options to modify default behavior:
* - `tables` (array): table names to restore (empty=all)
* - `allowDrop` (bool): allow DROP TABLE statements (default=true)
* - `haltOnError` (bool): halt execution when an error occurs? (default=false)
* - `maxSeconds` (int): max number of seconds allowed for execution (default=1200)
* - `findReplace` (array): find and replace in row data. Example: ['databass' => 'database']
* - `findReplaceCreateTable` (array): find and replace in create table statements.
* Example: ['DEFAULT CHARSET=utf8;' => 'DEFAULT CHARSET=utf8mb4;']
* @return true on success, false on failure. Call the errors() method to retrieve errors.
* @throws \Exception on fatal error
* @see WireDatabaseBackup::backup()
*
*/
public function restore($filename, array $options = array()) {

View File

@@ -733,13 +733,13 @@ class WireDatabasePDO extends Wire implements WireDatabase {
/**
* Retrieve new instance of WireDatabaseBackups ready to use with this connection
*
* See WireDatabaseBackup class for usage.
* See `WireDatabaseBackup` class for usage.
*
* #pw-group-custom
*
* @return WireDatabaseBackup
* @throws WireException|\Exception on fatal error
* @see WireDatabaseBackup
* @see WireDatabaseBackup::backup(), WireDatabaseBackup::restore()
*
*/
public function backups() {

View File

@@ -5,7 +5,18 @@
*
* Provides capability for sending POST/GET requests to URLs
*
* #pw-summary WireHttp enables you to send HTTP requests to URLs, download files, and more.
* #pw-summary WireHttp enables you to send HTTP requests to URLs, download files, and more.
* #pw-body =
* ~~~~~
* $http = new WireHttp();
* $response = $http->get("http://domain.com/path/");
* if($response !== false) {
* echo "Successful response: " . $sanitizer->entities($response);
* } else {
* echo "HTTP request failed: " . $http->getError();
* }
* ~~~~~
* #pw-body
*
* Thanks to @horst for his assistance with several methods in this class.
*
@@ -219,7 +230,7 @@ class WireHttp extends Wire {
* $response = $http->post("http://domain.com/path/", [
* 'foo' => bar',
* ]);
* if($response) {
* if($response !== false) {
* echo "Successful response: " . $sanitizer->entities($response);
* } else {
* echo "HTTP request failed: " . $http->getError();
@@ -244,7 +255,7 @@ class WireHttp extends Wire {
* $response = $http->get("http://domain.com/path/", [
* 'foo' => 'bar',
* ]);
* if($response) {
* if($response !== false) {
* echo "Successful response: " . $sanitizer->entities($response);
* } else {
* echo "HTTP request failed: " . $http->getError();