mirror of
https://github.com/processwire/processwire.git
synced 2025-08-10 16:54:44 +02:00
Addition of a $page->numParents() method/property which reflects the number of parents the page has, aka depth in the tree. This commit also has several small adjustments and fixes, including a fix for the issue introduced last week that caused issues with WireArray in versions of PHP prior to 7.x
This commit is contained in:
@@ -1031,3 +1031,26 @@ function wireRegion($key, $value = null) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new WireArray, add given $items to it, and return it
|
||||
*
|
||||
* @param array|WireArray $items
|
||||
* @return WireArray
|
||||
*
|
||||
*/
|
||||
function WireArray($items = array()) {
|
||||
return WireArray::newInstance($items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new PageArray, add given $items (pages) to it, and return it
|
||||
*
|
||||
* @param array|PageArray $items
|
||||
* @return WireArray
|
||||
*
|
||||
*/
|
||||
function PageArray($items = array()) {
|
||||
return PageArray::newInstance($items);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -611,6 +611,7 @@ class Page extends WireData implements \Countable, WireMatchable {
|
||||
'namePrevious' => 'p',
|
||||
'next' => 'm',
|
||||
'numChildren' => 's',
|
||||
'numParents' => 'm',
|
||||
'numDescendants' => 'm',
|
||||
'numLinks' => 't',
|
||||
'numReferences' => 't',
|
||||
@@ -2191,6 +2192,20 @@ class Page extends WireData implements \Countable, WireMatchable {
|
||||
return $this->traversal()->parents($this, $selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of parents (depth relative to homepage) that this page has, optionally filtered by a selector
|
||||
*
|
||||
* For example, homepage has 0 parents and root level pages have 1 parent (which is the homepage), and the
|
||||
* number increases the deeper the page is in the pages structure.
|
||||
*
|
||||
* @param string $selector Optional selector to filter by (default='')
|
||||
* @return int Number of parents
|
||||
*
|
||||
*/
|
||||
public function numParents($selector = '') {
|
||||
return $this->traversal()->numParents($this, $selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all parents from current page till the one matched by $selector
|
||||
*
|
||||
|
@@ -174,6 +174,28 @@ class PageTraversal {
|
||||
return strlen($selector) ? $parents->filter($selector) : $parents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return number of parents (depth relative to homepage) that this page has, optionally filtered by a selector
|
||||
*
|
||||
* For example, homepage has 0 parents and root level pages have 1 parent (which is the homepage), and the
|
||||
* number increases the deeper the page is in the pages structure.
|
||||
*
|
||||
* @param Page $page
|
||||
* @param string $selector Optional selector to filter by (default='')
|
||||
* @return int Number of parents
|
||||
*
|
||||
*/
|
||||
public function numParents(Page $page, $selector = '') {
|
||||
$num = 0;
|
||||
$parent = $page->parent();
|
||||
while($parent && $parent->id) {
|
||||
if($selector !== '' && !$parent->matches($selector)) continue;
|
||||
$num++;
|
||||
$parent = $parent->parent();
|
||||
}
|
||||
return $num;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all parent from current till the one matched by $selector
|
||||
*
|
||||
@@ -660,6 +682,7 @@ class PageTraversal {
|
||||
$languages = $options['languages'] ? $page->wire('languages') : null;
|
||||
$slashUrls = $page->template->slashUrls;
|
||||
$httpHostUrl = $options['http'] ? $page->wire('input')->httpHostUrl() : '';
|
||||
$urls = array();
|
||||
|
||||
if($options['language'] && $languages) {
|
||||
if(!$options['language'] instanceof Page) {
|
||||
@@ -682,6 +705,7 @@ class PageTraversal {
|
||||
|
||||
// add in historical URLs
|
||||
if($options['past'] && $modules->isInstalled('PagePathHistory')) {
|
||||
/** @var PagePathHistory $history */
|
||||
$history = $modules->get('PagePathHistory');
|
||||
$rootUrl = $page->wire('config')->urls->root;
|
||||
$pastPaths = $history->getPathHistory($page, array(
|
||||
@@ -691,11 +715,13 @@ class PageTraversal {
|
||||
foreach($pastPaths as $pathInfo) {
|
||||
$key = '';
|
||||
if(!empty($pathInfo['language'])) {
|
||||
/** @var Language $language */
|
||||
$language = $pathInfo['language'];
|
||||
if($options['languages']) {
|
||||
$key .= $pathInfo['language']->name . ';';
|
||||
$key .= $language->name . ';';
|
||||
} else {
|
||||
// they asked to have multi-language excluded
|
||||
if(!$pathInfo['language']->isDefault()) continue;
|
||||
if(!$language->isDefault()) continue;
|
||||
}
|
||||
}
|
||||
$key .= wireDate('c', $pathInfo['date']);
|
||||
@@ -774,6 +800,7 @@ class PageTraversal {
|
||||
*/
|
||||
public function referencing(Page $page, $field = false, $getCount = false) {
|
||||
$fieldName = '';
|
||||
$byField = null;
|
||||
if(is_bool($field) || is_null($field)) {
|
||||
$byField = $field ? true : false;
|
||||
} else if(is_string($field)) {
|
||||
@@ -793,7 +820,7 @@ class PageTraversal {
|
||||
foreach($page->template->fieldgroup as $f) {
|
||||
if($fieldName && $field->name != $fieldName) continue;
|
||||
if(!$f->type instanceof FieldtypePage) continue;
|
||||
if($byField) $itemsByField[$f->name] = $this->wire('pages')->newPageArray();
|
||||
if($byField) $itemsByField[$f->name] = $page->wire('pages')->newPageArray();
|
||||
$value = $page->get($f->name);
|
||||
if($value instanceof Page && $value->id) {
|
||||
$items->add($value);
|
||||
@@ -916,6 +943,7 @@ class PageTraversal {
|
||||
|
||||
$next = $page;
|
||||
do {
|
||||
/** @var Page $next */
|
||||
$next = $siblings->getNext($next, false);
|
||||
if(empty($selector) || !$next || $next->matches($selector)) break;
|
||||
} while($next && $next->id);
|
||||
@@ -959,6 +987,7 @@ class PageTraversal {
|
||||
|
||||
$prev = $page;
|
||||
do {
|
||||
/** @var Page $prev */
|
||||
$prev = $siblings->getPrev($prev, false);
|
||||
if(empty($selector) || !$prev || $prev->matches($selector)) break;
|
||||
} while($prev && $prev->id);
|
||||
@@ -1006,7 +1035,7 @@ class PageTraversal {
|
||||
* @param Page $page
|
||||
* @param string|array $selector Optional selector. When specified, will filter the found siblings.
|
||||
* @param PageArray $siblings Optional siblings to use instead of the default.
|
||||
* @return Page|NullPage Returns all matching pages before this one.
|
||||
* @return PageArray
|
||||
*
|
||||
*/
|
||||
public function prevAllSiblings(Page $page, $selector = '', PageArray $siblings = null) {
|
||||
|
@@ -60,7 +60,7 @@ class User extends Page {
|
||||
* }
|
||||
* ~~~~~
|
||||
*
|
||||
* @param string|Role|int May be Role name, object or ID.
|
||||
* @param string|Role|int $role May be Role name, object or ID.
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ class User extends Page {
|
||||
* $user->save();
|
||||
* ~~~~~
|
||||
*
|
||||
* @param string|int|Role Maybe Role name, object, or ID.
|
||||
* @param string|int|Role $role May be Role name, object, or ID.
|
||||
* @return bool Returns false if role not recognized, true otherwise
|
||||
*
|
||||
*/
|
||||
@@ -131,7 +131,7 @@ class User extends Page {
|
||||
* $user->save();
|
||||
* ~~~~~
|
||||
*
|
||||
* @param string|int|Role May be Role name, object or ID.
|
||||
* @param string|int|Role $role May be Role name, object or ID.
|
||||
* @return bool false if role not recognized, true otherwise
|
||||
*
|
||||
*/
|
||||
|
@@ -16,7 +16,7 @@
|
||||
* https://processwire.com
|
||||
*
|
||||
* @method WireArray and($item)
|
||||
* @method WireArray new($items = array())
|
||||
* @method static WireArray new($items = array())
|
||||
* @property int $count Number of items
|
||||
* @property Wire|null $first First item
|
||||
* @property Wire|null $last Last item
|
||||
@@ -2446,39 +2446,36 @@ class WireArray extends Wire implements \IteratorAggregate, \ArrayAccess, \Count
|
||||
// multiple items specified as arguments
|
||||
$items = $arguments;
|
||||
}
|
||||
$a = new $class();
|
||||
if(WireArray::iterable($items)) {
|
||||
$a->import($items);
|
||||
} else if($items !== null) {
|
||||
$a->add($items);
|
||||
}
|
||||
return $a;
|
||||
return self::newInstance($items, $class);
|
||||
} else {
|
||||
throw new WireException("Unrecognized static method: $class::$name()");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new WireArray instance of this type, optionally adding $items to it
|
||||
* Create new instance of this class
|
||||
*
|
||||
* This method call be called statically or non-statically, but is primarily useful as a static method call.
|
||||
* Method for internal use, use `$a = WireArray::new($items)` or `$a = WireArrray($items)` instead.
|
||||
*
|
||||
* ~~~~~~
|
||||
* // Create new WireArray with a, b and c items
|
||||
* $a = WireArray::new([ 'a', 'b', 'c' ]);
|
||||
* #pw-internal
|
||||
*
|
||||
* // This also works when called statically (array syntax can optionally be omitted)
|
||||
* $a = WireArray::new('a', 'b', 'c');
|
||||
* ~~~~~~
|
||||
*
|
||||
* @param array|WireArray|mixed|null $items Items (or item) to add to new WireArray
|
||||
* @param array|WireArray|null $items Items to add or omit (null) for none
|
||||
* @param string $class Class name to instantiate or omit for called class
|
||||
* @return WireArray
|
||||
* @since 3.0.117
|
||||
*
|
||||
*/
|
||||
public function ___new($items = null) {
|
||||
$a = self::new($items);
|
||||
$this->wire($a);
|
||||
public static function newInstance($items = null, $class = '') {
|
||||
if(empty($class)) $class = get_called_class();
|
||||
/** @var WireArray $a */
|
||||
$a = new $class();
|
||||
if($items instanceof WireArray) {
|
||||
$items->wire($a);
|
||||
$a->import($items);
|
||||
} else if(is_array($items)) {
|
||||
$a->import($items);
|
||||
} else if($items !== null) {
|
||||
$a->add($items);
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
}
|
||||
|
@@ -386,6 +386,7 @@ class WireFileTools extends Wire {
|
||||
|
||||
for($i = 0; $i < $zip->numFiles; $i++) {
|
||||
$name = $zip->getNameIndex($i);
|
||||
if(strpos($name, '..') !== false) continue;
|
||||
if($zip->extractTo($dst, $name)) {
|
||||
$names[$i] = $name;
|
||||
$filename = $dst . ltrim($name, '/');
|
||||
|
@@ -1814,6 +1814,8 @@ class FieldtypeComments extends FieldtypeMulti {
|
||||
$updatePropertyCounts = array();
|
||||
$skipUpdateProperties = array('id', 'created_user', 'created_users_id');
|
||||
|
||||
if(!$comments) return null;
|
||||
|
||||
foreach($comments as $comment) {
|
||||
if($comment->status == Comment::statusSpam) continue;
|
||||
$key = $this->getCommentExportKey($comment);
|
||||
|
@@ -103,7 +103,7 @@ class SelectableOption extends WireData { // implements LanguagesValueInterface
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
protected function getProperty($property) {
|
||||
public function getProperty($property) {
|
||||
if($this->wire('languages')) {
|
||||
$language = $this->wire('user')->language;
|
||||
if($language->isDefault()) {
|
||||
|
@@ -89,9 +89,13 @@ class InputfieldCheckbox extends Inputfield {
|
||||
$attrs = $this->getAttributes();
|
||||
$attrs['value'] = $this->checkedValue;
|
||||
|
||||
if($this->getSetting('entityEncodeLabel') !== false) {
|
||||
$label = $this->entityEncode($label);
|
||||
}
|
||||
|
||||
$out =
|
||||
"<label><input type='checkbox' " . $this->getAttributesString($attrs) . " />" .
|
||||
"<span class='pw-no-select'>" . $this->entityEncode($label) . "</span></label>";
|
||||
"<span class='pw-no-select'>$label</span></label>";
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
@@ -72,6 +72,7 @@
|
||||
* @method string executeConfig() ListerPro
|
||||
* @method string executeActions() ListerPro
|
||||
* @method string executeSave() ListerPro
|
||||
* @method string renderExtraTabs() #pw-hooker
|
||||
*
|
||||
*
|
||||
* @todo make system fields hookable for output like markupValue is for custom fields
|
||||
@@ -1823,7 +1824,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
||||
|
||||
/**
|
||||
* Render additional tabs, setup so that descending classes can use as a template method
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
@@ -1832,9 +1833,24 @@ class ProcessPageLister extends Process implements ConfigurableModule {
|
||||
$resetLabel = $this->_('Reset filters and columns to default');
|
||||
$out = "<div id='ProcessListerRefreshTab' title='$refreshLabel' class='WireTab WireTabTip'></div>";
|
||||
$out .= "<div id='ProcessListerResetTab' title='$resetLabel' class='WireTab WireTabTip'></div>";
|
||||
$out .= $this->renderExtraTabs();
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Optionally hook this if you want to add additional tabs
|
||||
*
|
||||
* See renderExtras() method above for examples.
|
||||
*
|
||||
* #pw-hooker
|
||||
*
|
||||
* @return string Markup for extra tabs
|
||||
*
|
||||
*/
|
||||
public function ___renderExtraTabs() {
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the session values for external assets
|
||||
*
|
||||
|
@@ -605,7 +605,13 @@ class ProcessPagesExportImport extends Process {
|
||||
$path = rtrim($importParentPath . substr($path, strlen($missingParentPath)), '/') . '/';
|
||||
}
|
||||
}
|
||||
if($path == $item['path']) $path = $importParentPath . trim($path, '/') . '/';
|
||||
if($path == $item['path']) {
|
||||
if(strpos($path, $importParentPath) === 0) {
|
||||
// parent already present in path
|
||||
} else {
|
||||
$path = $importParentPath . trim($path, '/') . '/';
|
||||
}
|
||||
}
|
||||
$a['pages'][$key]['path'] = $path;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user