mirror of
https://github.com/processwire/processwire.git
synced 2025-08-17 20:11:46 +02:00
Refactoring of the PagesEditor class, primarily addition of a new PagesNames class for handling page names, duplicate names, untitled pages, incrementing page names, etc.
This commit is contained in:
@@ -806,6 +806,16 @@ $config->pageNameCharset = 'ascii';
|
|||||||
*/
|
*/
|
||||||
$config->pageNameWhitelist = '-_.abcdefghijklmnopqrstuvwxyz0123456789æåäßöüđжхцчшщюяàáâèéëêěìíïîõòóôøùúûůñçčćďĺľńňŕřšťýžабвгдеёзийклмнопрстуфыэęąśłżź';
|
$config->pageNameWhitelist = '-_.abcdefghijklmnopqrstuvwxyz0123456789æåäßöüđжхцчшщюяàáâèéëêěìíïîõòóôøùúûůñçčćďĺľńňŕřšťýžабвгдеёзийклмнопрстуфыэęąśłżź';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name to use for untitled pages
|
||||||
|
*
|
||||||
|
* When page has this name, the name will be changed automatically (to a field like title) when it is possible to do so.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$config->pageNameUntitled = "untitled";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum paginations
|
* Maximum paginations
|
||||||
*
|
*
|
||||||
|
@@ -77,6 +77,7 @@
|
|||||||
*
|
*
|
||||||
* @property string $pageNameCharset Character set for page names, must be 'ascii' (default, lowercase) or 'UTF8' (uppercase). #pw-group-URLs
|
* @property string $pageNameCharset Character set for page names, must be 'ascii' (default, lowercase) or 'UTF8' (uppercase). #pw-group-URLs
|
||||||
* @property string $pageNameWhitelist Whitelist of characters allowed in UTF8 page names. #pw-group-URLs
|
* @property string $pageNameWhitelist Whitelist of characters allowed in UTF8 page names. #pw-group-URLs
|
||||||
|
* @property string $pageNameUntitled Name to use for untitled pages (default="untitled"). #pw-group-URLs
|
||||||
* @property string $pageNumUrlPrefix Prefix used for pagination URLs. Default is "page", resulting in "/page1", "/page2", etc. #pw-group-URLs
|
* @property string $pageNumUrlPrefix Prefix used for pagination URLs. Default is "page", resulting in "/page1", "/page2", etc. #pw-group-URLs
|
||||||
* @property array $pageNumUrlPrefixes Multiple prefixes that may be used for detecting pagination (internal use, for multi-language) #pw-group-URLs
|
* @property array $pageNumUrlPrefixes Multiple prefixes that may be used for detecting pagination (internal use, for multi-language) #pw-group-URLs
|
||||||
* @property int $maxUrlSegments Maximum number of extra stacked URL segments allowed in a page's URL (including page numbers) #pw-group-URLs
|
* @property int $maxUrlSegments Maximum number of extra stacked URL segments allowed in a page's URL (including page numbers) #pw-group-URLs
|
||||||
|
@@ -122,6 +122,12 @@ class Pages extends Wire {
|
|||||||
*/
|
*/
|
||||||
protected $editor;
|
protected $editor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var PagesNames
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $names;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var PagesLoaderCache
|
* @var PagesLoaderCache
|
||||||
*
|
*
|
||||||
@@ -1343,6 +1349,17 @@ class Pages extends Wire {
|
|||||||
if(!$this->editor) $this->editor = $this->wire(new PagesEditor($this));
|
if(!$this->editor) $this->editor = $this->wire(new PagesEditor($this));
|
||||||
return $this->editor;
|
return $this->editor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return PagesNames
|
||||||
|
*
|
||||||
|
* #pw-internal
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function names() {
|
||||||
|
if(!$this->names) $this->names = $this->wire(new PagesNames($this));
|
||||||
|
return $this->names;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return PagesLoaderCache
|
* @return PagesLoaderCache
|
||||||
|
@@ -22,20 +22,12 @@ class PagesEditor extends Wire {
|
|||||||
*/
|
*/
|
||||||
protected $cloning = 0;
|
protected $cloning = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Name for autogenerated page names when fields to generate name aren't populated
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected $untitledPageName = 'untitled';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Pages
|
* @var Pages
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected $pages;
|
protected $pages;
|
||||||
|
|
||||||
public function __construct(Pages $pages) {
|
public function __construct(Pages $pages) {
|
||||||
$this->pages = $pages;
|
$this->pages = $pages;
|
||||||
|
|
||||||
@@ -283,8 +275,11 @@ class PagesEditor extends Wire {
|
|||||||
* Auto-populate some fields for a new page that does not yet exist
|
* Auto-populate some fields for a new page that does not yet exist
|
||||||
*
|
*
|
||||||
* Currently it does this:
|
* Currently it does this:
|
||||||
|
*
|
||||||
|
* - Assigns a parent if one is not already assigned.
|
||||||
* - Sets up a unique page->name based on the format or title if one isn't provided already.
|
* - Sets up a unique page->name based on the format or title if one isn't provided already.
|
||||||
* - Assigns a 'sort' value'.
|
* - Assigns a sort value.
|
||||||
|
* - Populates any default values for fields.
|
||||||
*
|
*
|
||||||
* @param Page $page
|
* @param Page $page
|
||||||
*
|
*
|
||||||
@@ -292,9 +287,9 @@ class PagesEditor extends Wire {
|
|||||||
public function setupNew(Page $page) {
|
public function setupNew(Page $page) {
|
||||||
|
|
||||||
$parent = $page->parent();
|
$parent = $page->parent();
|
||||||
if(!$parent->id) {
|
|
||||||
// auto-assign a parent, if we can find one in family settings
|
|
||||||
|
|
||||||
|
// assign parent
|
||||||
|
if(!$parent->id) {
|
||||||
$parentTemplates = $page->template->parentTemplates;
|
$parentTemplates = $page->template->parentTemplates;
|
||||||
$parent = null;
|
$parent = null;
|
||||||
|
|
||||||
@@ -307,13 +302,17 @@ class PagesEditor extends Wire {
|
|||||||
if($parent->id) $page->parent = $parent;
|
if($parent->id) $page->parent = $parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!strlen($page->name)) $this->pages->setupPageName($page);
|
// assign page name
|
||||||
|
if(!strlen($page->name)) {
|
||||||
|
$this->pages->setupPageName($page); // call through $pages intended, so it can be hooked
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign sort order
|
||||||
if($page->sort < 0) {
|
if($page->sort < 0) {
|
||||||
// auto assign a sort
|
|
||||||
$page->sort = $page->parent->numChildren();
|
$page->sort = $page->parent->numChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assign any default values for fields
|
||||||
foreach($page->template->fieldgroup as $field) {
|
foreach($page->template->fieldgroup as $field) {
|
||||||
if($page->isLoaded($field->name)) continue; // value already set
|
if($page->isLoaded($field->name)) continue; // value already set
|
||||||
if(!$page->hasField($field)) continue; // field not valid for page
|
if(!$page->hasField($field)) continue; // field not valid for page
|
||||||
@@ -348,115 +347,7 @@ class PagesEditor extends Wire {
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function setupPageName(Page $page, array $options = array()) {
|
public function setupPageName(Page $page, array $options = array()) {
|
||||||
|
return $this->pages->names()->setupNewPageName($page, isset($options['format']) ? $options['format'] : '');
|
||||||
$defaults = array(
|
|
||||||
'format' => '',
|
|
||||||
);
|
|
||||||
$options = array_merge($defaults, $options);
|
|
||||||
$format = $options['format'];
|
|
||||||
$sanitizer = $this->wire('sanitizer');
|
|
||||||
|
|
||||||
if(strlen($page->name)) {
|
|
||||||
// make sure page starts with "untitled" or "untitled-"
|
|
||||||
if($page->name != $this->untitledPageName && strpos($page->name, "$this->untitledPageName-") !== 0) {
|
|
||||||
// page already has a name and it's not a temporary/untitled one
|
|
||||||
// so we do nothing
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
// page starts with our untitled name, but is it in the exact format we use?
|
|
||||||
if($page->name != $this->untitledPageName) {
|
|
||||||
$parts = explode('-', $page->name);
|
|
||||||
array_shift($parts); // shift off 'untitled';
|
|
||||||
$parts = implode('', $parts); // put remaining back together
|
|
||||||
// if we were left with something other than digits,
|
|
||||||
// this is not an auto-generated name, so leave as-is
|
|
||||||
if(!ctype_digit($parts)) return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!strlen($format)) {
|
|
||||||
$parent = $page->parent();
|
|
||||||
if($parent && $parent->id) $format = $parent->template->childNameFormat;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!strlen($format)) {
|
|
||||||
if(strlen($page->title)) {
|
|
||||||
// default format is title
|
|
||||||
$format = 'title';
|
|
||||||
} else {
|
|
||||||
// if page has no title, default format is date
|
|
||||||
$format = 'Y-m-d H:i:s';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$pageName = '';
|
|
||||||
|
|
||||||
if(strlen($format)) {
|
|
||||||
// @todo add option to auto-gen name from any page property/field
|
|
||||||
|
|
||||||
if($format == 'title') {
|
|
||||||
if(strlen($page->title)) $pageName = $page->title;
|
|
||||||
else $pageName = $this->untitledPageName;
|
|
||||||
|
|
||||||
} else if(!ctype_alnum($format) && !preg_match('/^[-_a-zA-Z0-9]+$/', $format)) {
|
|
||||||
// it is a date format
|
|
||||||
$pageName = date($format);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// predefined format
|
|
||||||
$pageName = $format;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if(strlen($page->title)) {
|
|
||||||
$pageName = $page->title;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// no name will be assigned
|
|
||||||
}
|
|
||||||
|
|
||||||
if($pageName == $this->untitledPageName && strpos($page->name, $this->untitledPageName) === 0) {
|
|
||||||
// page already has untitled name, and there's no need to re-assign the untitled name
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$name = '';
|
|
||||||
if(strlen($pageName)) {
|
|
||||||
// make the name unique
|
|
||||||
|
|
||||||
if($this->wire('config')->pageNameCharset === 'UTF8') {
|
|
||||||
$pageName = $sanitizer->pageNameUTF8($pageName);
|
|
||||||
} else {
|
|
||||||
$pageName = $sanitizer->pageName($pageName, Sanitizer::translate);
|
|
||||||
}
|
|
||||||
$numChildren = $page->parent->numChildren();
|
|
||||||
$n = 0;
|
|
||||||
|
|
||||||
do {
|
|
||||||
$name = $pageName;
|
|
||||||
if($n > 0) {
|
|
||||||
$nStr = "-" . ($numChildren + $n);
|
|
||||||
if($n > 100) {
|
|
||||||
// if we've reached this many dups, start adding a random element to it
|
|
||||||
$nStr = '_' . mt_rand() . $nStr;
|
|
||||||
}
|
|
||||||
if(strlen($name) + strlen($nStr) > Pages::nameMaxLength) {
|
|
||||||
$name = substr($name, 0, Pages::nameMaxLength - strlen($nStr));
|
|
||||||
}
|
|
||||||
$name .= $nStr;
|
|
||||||
}
|
|
||||||
$n++;
|
|
||||||
} while($n < 200 && $this->pages->count("parent=$page->parent, name=" . $sanitizer->selectorValue($name) . ", include=all"));
|
|
||||||
|
|
||||||
if($this->pages->count("parent=$page->parent, name=" . $sanitizer->selectorValue($name) . ", include=all") > 0) {
|
|
||||||
// this is now extremely unlikely
|
|
||||||
throw new WireException("Unable to generate unique name for page $page->id");
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->name = $sanitizer->pageNameUTF8($name);
|
|
||||||
$page->set('_hasAutogenName', true); // for savePageQuery, provides adjustName behavior for new pages
|
|
||||||
}
|
|
||||||
|
|
||||||
return $name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -563,7 +454,9 @@ class PagesEditor extends Wire {
|
|||||||
}
|
}
|
||||||
$sql = '';
|
$sql = '';
|
||||||
|
|
||||||
if(strpos($page->name, $this->untitledPageName) === 0) $this->pages->setupPageName($page);
|
if($this->pages->names()->isUntitledPageName($page->name)) {
|
||||||
|
$this->pages->setupPageName($page);
|
||||||
|
}
|
||||||
|
|
||||||
$data = array(
|
$data = array(
|
||||||
'parent_id' => (int) $page->parent_id,
|
'parent_id' => (int) $page->parent_id,
|
||||||
@@ -632,53 +525,19 @@ class PagesEditor extends Wire {
|
|||||||
$query->bindValue(":$column", $value, is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
|
$query->bindValue(":$column", $value, is_int($value) ? \PDO::PARAM_INT : \PDO::PARAM_STR);
|
||||||
}
|
}
|
||||||
|
|
||||||
$n = 0;
|
|
||||||
$tries = 0;
|
$tries = 0;
|
||||||
$maxTries = 100;
|
$maxTries = 100;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
$result = false;
|
$result = false;
|
||||||
$errorCode = 0;
|
$keepTrying = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$result = false;
|
|
||||||
$result = $database->execute($query);
|
$result = $database->execute($query);
|
||||||
|
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
|
$keepTrying = $this->savePageQueryException($page, $query, $e, $options);
|
||||||
$errorCode = $e->getCode();
|
if(!$keepTrying) throw $e;
|
||||||
|
|
||||||
// while setupNew() already attempts to uniqify a page name with an incrementing
|
|
||||||
// number, there is a chance that two processes running at once might end up with
|
|
||||||
// the same number, so we account for the possibility here by re-trying queries
|
|
||||||
// that trigger duplicate-entry exceptions
|
|
||||||
|
|
||||||
if($errorCode == 23000 && ($page->_hasAutogenName || $options['adjustName'])) {
|
|
||||||
// Integrity constraint violation: 1062 Duplicate entry 'background-3552' for key 'name3894_parent_id'
|
|
||||||
// attempt to re-generate page name
|
|
||||||
$nameField = 'name';
|
|
||||||
// account for the duplicate possibly being a multi-language name field
|
|
||||||
if($this->wire('languages') && preg_match('/\b(name\d*)_parent_id\b/', $e->getMessage(), $matches)) $nameField = $matches[1];
|
|
||||||
// get either 'name' or 'name123' (where 123 is language ID)
|
|
||||||
$pageName = $page->$nameField;
|
|
||||||
// determine if current name format already has a trailing number
|
|
||||||
if(preg_match('/^(.+?)-(\d+)$/', $pageName, $matches)) {
|
|
||||||
// page already has a trailing number
|
|
||||||
$n = (int) $matches[2];
|
|
||||||
$pageName = $matches[1];
|
|
||||||
}
|
|
||||||
$nStr = '-' . (++$n);
|
|
||||||
if(strlen($pageName) + strlen($nStr) > Pages::nameMaxLength) $pageName = substr($pageName, 0, Pages::nameMaxLength - strlen($nStr));
|
|
||||||
$page->name = $pageName . $nStr;
|
|
||||||
$query->bindValue(":$nameField", $this->wire('sanitizer')->pageName($page->name, Sanitizer::toAscii));
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// a different exception that we don't catch, so re-throw it
|
|
||||||
throw $e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} while($keepTrying && (++$tries < $maxTries));
|
||||||
} while($errorCode == 23000 && (++$tries < $maxTries));
|
|
||||||
|
|
||||||
if($result && ($isNew || !$page->id)) $page->id = $database->lastInsertId();
|
if($result && ($isNew || !$page->id)) $page->id = $database->lastInsertId();
|
||||||
if($options['forceID']) $page->id = (int) $options['forceID'];
|
if($options['forceID']) $page->id = (int) $options['forceID'];
|
||||||
@@ -686,6 +545,47 @@ class PagesEditor extends Wire {
|
|||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle Exception for savePageQuery()
|
||||||
|
*
|
||||||
|
* While setupNew() already attempts to uniqify a page name with an incrementing
|
||||||
|
* number, there is a chance that two processes running at once might end up with
|
||||||
|
* the same number, so we account for the possibility here by re-trying queries
|
||||||
|
* that trigger duplicate-entry exceptions.
|
||||||
|
*
|
||||||
|
* Example of actual exception text, for reference:
|
||||||
|
* Integrity constraint violation: 1062 Duplicate entry 'background-3552' for key 'name3894_parent_id'
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @param \PDOStatement $query
|
||||||
|
* @param \PDOException|\Exception $exception
|
||||||
|
* @param array $options
|
||||||
|
* @return bool True if it should give $query another shot, false if not
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected function savePageQueryException(Page $page, $query, $exception, array $options) {
|
||||||
|
|
||||||
|
$errorCode = $exception->getCode();
|
||||||
|
if($errorCode != 23000) return false;
|
||||||
|
|
||||||
|
if(!$this->pages->names()->hasAutogenName($page) && !$options['adjustName']) return false;
|
||||||
|
|
||||||
|
// account for the duplicate possibly being a multi-language name field
|
||||||
|
if($this->wire('languages') && preg_match('/\b(name\d*)_parent_id\b/', $exception->getMessage(), $matches)) {
|
||||||
|
$nameField = $matches[1];
|
||||||
|
} else {
|
||||||
|
$nameField = 'name';
|
||||||
|
}
|
||||||
|
|
||||||
|
// get either 'name' or 'name123' (where 123 is language ID)
|
||||||
|
$pageName = $page->get($nameField);
|
||||||
|
$pageName = $this->pages->names()->incrementName($pageName);
|
||||||
|
$page->set($nameField, $pageName);
|
||||||
|
$query->bindValue(":$nameField", $this->wire('sanitizer')->pageName($pageName, Sanitizer::toAscii));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save individual Page fields and supporting actions
|
* Save individual Page fields and supporting actions
|
||||||
*
|
*
|
||||||
|
535
wire/core/PagesNames.php
Normal file
535
wire/core/PagesNames.php
Normal file
@@ -0,0 +1,535 @@
|
|||||||
|
<?php namespace ProcessWire;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProcessWire Pages Names
|
||||||
|
*
|
||||||
|
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer
|
||||||
|
* https://processwire.com
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PagesNames extends Wire {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Pages
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $pages;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Name for untitled/temporary pages
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $untitledPageName = 'untitled';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delimiters that can separate words in page names
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $delimiters = array('-', '_', '.');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default delimiter for separating words in page names
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
protected $delimiter = '-';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct
|
||||||
|
*
|
||||||
|
* @param Pages $pages
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function __construct(Pages $pages) {
|
||||||
|
$this->pages = $pages;
|
||||||
|
$pages->wire($this);
|
||||||
|
$untitled = $this->wire('config')->pageNameUntitled;
|
||||||
|
if($untitled) $this->untitledPageName = $untitled;
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assign a name to given Page (if it doesn’t already have one)
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @param string $format
|
||||||
|
* @return string Returns page name that was assigned
|
||||||
|
* @throws WireException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function setupNewPageName(Page $page, $format = '') {
|
||||||
|
|
||||||
|
$pageName = $page->name;
|
||||||
|
|
||||||
|
// check if page already has a non-“untitled” name assigned that we should leave alone
|
||||||
|
if(strlen($pageName) && !$this->isUntitledPageName($pageName)) return '';
|
||||||
|
|
||||||
|
// determine what format should be used for the generated page name
|
||||||
|
if(!strlen($format)) $format = $this->defaultPageNameFormat($page);
|
||||||
|
|
||||||
|
// generate a page name from determined format
|
||||||
|
$pageName = $this->pageNameFromFormat($page, $format);
|
||||||
|
|
||||||
|
// ensure page name is unique
|
||||||
|
$pageName = $this->uniquePageName($pageName, $page);
|
||||||
|
|
||||||
|
// assign to page
|
||||||
|
$page->name = $pageName;
|
||||||
|
|
||||||
|
// indicate that page has auto-generated name for savePageQuery (provides adjustName behavior for new pages)
|
||||||
|
$page->setQuietly('_hasAutogenName', $pageName);
|
||||||
|
|
||||||
|
return $pageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the given page have an auto-generated name (during this request)?
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @return string|bool Returns auto-generated name if present, or boolean false if not
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function hasAutogenName(Page $page) {
|
||||||
|
$name = $page->get('_hasAutogenName');
|
||||||
|
if(empty($name)) $name = false;
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is given page name an untitled page name?
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @return bool
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function isUntitledPageName($name) {
|
||||||
|
list($namePrefix,) = $this->nameAndNumber($name);
|
||||||
|
return $namePrefix === $this->untitledPageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If given name has a numbered suffix, return array with name (excluding suffix) and the numbered suffix
|
||||||
|
*
|
||||||
|
* Returns array like `[ 'name', 123 ]` where `name` is name without the suffix, and `123` is the numbered suffix.
|
||||||
|
* If the name did not have a numbered suffix, then the 123 will be 0 and `name` will be the given `$name`.
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param string $delimiter Character(s) that separate name and numbered suffix
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function nameAndNumber($name, $delimiter = '') {
|
||||||
|
if(empty($delimiter)) $delimiter = $this->delimiter;
|
||||||
|
$fail = array($name, 0);
|
||||||
|
if(strpos($name, $delimiter) === false) return $fail;
|
||||||
|
$parts = explode($delimiter, $name);
|
||||||
|
$suffix = array_pop($parts);
|
||||||
|
if(!ctype_digit($suffix)) return $fail;
|
||||||
|
$suffix = ltrim($suffix, '0');
|
||||||
|
return array(implode($delimiter, $parts), (int) $suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name format string that should be used for given $page if no name was assigned
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function defaultPageNameFormat(Page $page) {
|
||||||
|
|
||||||
|
$format = 'untitled-time'; // default fallback format
|
||||||
|
$parent = $page->parent();
|
||||||
|
|
||||||
|
if($parent && $parent->id && $parent->template->childNameFormat) {
|
||||||
|
// if format specified with parent template, use that
|
||||||
|
$format = $parent->template->childNameFormat;
|
||||||
|
|
||||||
|
} else if(strlen("$page->title")) {
|
||||||
|
// default format is title (when the page has one)
|
||||||
|
$format = 'title';
|
||||||
|
|
||||||
|
} else if($this->wire('languages') && $page->title instanceof LanguagesValueInterface) {
|
||||||
|
// check for multi-language title
|
||||||
|
/** @var LanguagesPageFieldValue $pageTitle */
|
||||||
|
$pageTitle = $page->title;
|
||||||
|
if(strlen($pageTitle->getDefaultValue())) $format = 'title';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $format;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a page name from the given format
|
||||||
|
*
|
||||||
|
* - Returns a generated page name that is not yet assigned to the page.
|
||||||
|
* - If no format is specified, it first falls back to page parent template `childNameFormat` property (if present).
|
||||||
|
* - If no format can be determined, it falls back to a randomly generated page name.
|
||||||
|
* - Does not check if page name is already in use.
|
||||||
|
*
|
||||||
|
* Options for $format argument:
|
||||||
|
*
|
||||||
|
* - `title` Build name based on “title” field.
|
||||||
|
* - `field` Build name based on any other field name you choose, replace “field” with any field name.
|
||||||
|
* - `text` Text already in the right format (that’s not a field name) will be used literally, replace “text” with your text.
|
||||||
|
* - `random` Randomly generates a name.
|
||||||
|
* - `untitled` Uses an auto-incremented “untitled” name.
|
||||||
|
* - `untitled-time` Uses an “untitled” name followed by date/time number string.
|
||||||
|
* - `a|b|c` Builds name from first matching field name, where a|b|c are your field names.
|
||||||
|
* - `{field}` Builds name from the given field name.
|
||||||
|
* - `{a|b|c}` Builds name first matching field name, where a|b|c would be replaced with your field names.
|
||||||
|
* - `date:Y-m-d-H-i` Builds name from current date - replace “Y-m-d-H-i” with desired wireDate() format.
|
||||||
|
* - `string with space` A string that does not match one of the above and has space is assumed to be a wireDate() format.
|
||||||
|
* - `string with /` A string that does not match one of the above and has a “/” slash is assumed to be a wireDate() format.
|
||||||
|
*
|
||||||
|
* For formats above that accept a wireDate() format, see `WireDateTime::date()` method for format details. It accepts PHP
|
||||||
|
* date() format, PHP strftime() format, as well as some other predefined options.
|
||||||
|
*
|
||||||
|
* @param Page $page
|
||||||
|
* @param string $format Optional format. If not specified, pulls from $page’s parent template.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function pageNameFromFormat(Page $page, $format = '') {
|
||||||
|
|
||||||
|
if(!strlen($format)) $format = $this->defaultPageNameFormat($page);
|
||||||
|
$format = trim($format);
|
||||||
|
$name = '';
|
||||||
|
|
||||||
|
if($format === 'title' && !strlen(trim((string) $page->title))) {
|
||||||
|
$format = 'untitled-time';
|
||||||
|
}
|
||||||
|
|
||||||
|
if($format === 'title') {
|
||||||
|
// title
|
||||||
|
$name = trim((string) $page->title);
|
||||||
|
|
||||||
|
} else if($format === 'random') {
|
||||||
|
// globally unique randomly generated page name
|
||||||
|
$name = $this->uniqueRandomPageName();
|
||||||
|
|
||||||
|
} else if($format === 'untitled') {
|
||||||
|
// just untitled
|
||||||
|
$name = $this->untitledPageName();
|
||||||
|
|
||||||
|
} else if($format === 'untitled-time') {
|
||||||
|
// untitled with datetime, i.e. “untitled-0yymmddhhmmss” (note leading 0 differentiates from increment)
|
||||||
|
$dateStr = date('ymdHis');
|
||||||
|
$name = $this->untitledPageName() . '-0' . $dateStr;
|
||||||
|
|
||||||
|
} else if(strpos($format, '}')) {
|
||||||
|
// string with {field_name} to text
|
||||||
|
$name = $page->getText($format, true, false);
|
||||||
|
|
||||||
|
} else if(strpos($format, '|')) {
|
||||||
|
// field names separated by "|" until one matches
|
||||||
|
$name = $page->getUnformatted($format);
|
||||||
|
|
||||||
|
} else if(strpos($format, 'date:') === 0) {
|
||||||
|
// specified date format
|
||||||
|
list(, $format) = explode('date:', $format);
|
||||||
|
if(empty($format)) $format = 'Y-m-d H:i:s';
|
||||||
|
$name = wireDate(trim($format));
|
||||||
|
|
||||||
|
} else if(strpos($format, ' ') !== false || strpos($format, '/') !== false) {
|
||||||
|
// date assumed when spaces or slashes present in format
|
||||||
|
$name = wireDate($format);
|
||||||
|
|
||||||
|
} else if($this->wire('sanitizer')->fieldName($format) === $format) {
|
||||||
|
// single field name or predefined string
|
||||||
|
// this can also return null, which falls back to if() statement below
|
||||||
|
$name = (string) $page->getUnformatted($format);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strlen($name)) {
|
||||||
|
// predefined string that is not a field name
|
||||||
|
$name = $format;
|
||||||
|
}
|
||||||
|
|
||||||
|
$utf8 = $this->wire('config')->pageNameCharset === 'UTF8';
|
||||||
|
$sanitizer = $this->wire('sanitizer');
|
||||||
|
$name = $utf8 ? $sanitizer->pageNameUTF8($name) : $sanitizer->pageName($name, Sanitizer::translate);
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a unique page name
|
||||||
|
*
|
||||||
|
* 1. If given no arguments, it returns a random globally unique page name.
|
||||||
|
* 2. If given just a $name, it returns that name (if globally unique), or an incremented version of it that is globally unique.
|
||||||
|
* 3. If given both $page and $name, it returns given name if unique in parent, or incremented version that is.
|
||||||
|
* 4. If given just a $page, the name is pulled from $page and behavior is the same as #3 above.
|
||||||
|
*
|
||||||
|
* The returned value is not yet assigned to the given $page, so if it is something different than what
|
||||||
|
* is already on $page, you’ll want to assign it manually after this.
|
||||||
|
*
|
||||||
|
* @param string|Page $name Name to make unique, or Page to pull it from.
|
||||||
|
* @param Page||string|null You may optionally specify Page or name in this argument if not in the first.
|
||||||
|
*
|
||||||
|
* @return string Returns unique name
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function uniquePageName($name = '', $page = null) {
|
||||||
|
|
||||||
|
$options = array();
|
||||||
|
|
||||||
|
if($name instanceof Page) {
|
||||||
|
$_name = is_string($page) ? $page : '';
|
||||||
|
$page = $name;
|
||||||
|
$name = $_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($page) {
|
||||||
|
$parent = $page->parent();
|
||||||
|
if(!strlen($name)) $name = $page->name;
|
||||||
|
$options['parent'] = $parent;
|
||||||
|
$options['page'] = $page;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!strlen($name)) {
|
||||||
|
$name = $this->uniqueRandomPageName();
|
||||||
|
}
|
||||||
|
|
||||||
|
while($this->pageNameExists($name, $options)) {
|
||||||
|
$name = $this->incrementName($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If name exceeds maxLength, truncate it, while keeping any numbered suffixes in place
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param int $maxLength
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function adjustNameLength($name, $maxLength = 0) {
|
||||||
|
|
||||||
|
if($maxLength < 1) $maxLength = Pages::nameMaxLength;
|
||||||
|
if(strlen($name) <= $maxLength) return $name;
|
||||||
|
|
||||||
|
$trims = implode('', $this->delimiters);
|
||||||
|
$pos = 0;
|
||||||
|
|
||||||
|
list($namePrefix, $numberSuffix) = $this->nameAndNumber($name);
|
||||||
|
|
||||||
|
if($namePrefix !== $name) {
|
||||||
|
$numberSuffix = $this->delimiter . $numberSuffix;
|
||||||
|
$maxLength -= strlen($numberSuffix);
|
||||||
|
} else {
|
||||||
|
$numberSuffix = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strlen($namePrefix) > $maxLength) {
|
||||||
|
$namePrefix = substr($namePrefix, 0, $maxLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
// find word delimiter closest to end of string
|
||||||
|
foreach($this->delimiters as $c) {
|
||||||
|
$p = strrpos($namePrefix, $c);
|
||||||
|
if((int) $p > $pos) $pos = $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
// use word delimiter pos as maxLength when it’s relatively close to the end
|
||||||
|
if(!$pos || $pos < (strlen($namePrefix) / 1.3)) $pos = $maxLength;
|
||||||
|
|
||||||
|
$name = substr($namePrefix, 0, $pos);
|
||||||
|
$name = rtrim($name, $trims);
|
||||||
|
|
||||||
|
// append number suffix if there was one
|
||||||
|
if($numberSuffix) $name .= $numberSuffix;
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the suffix of a page name, or add one if not present
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param int|null $num Number to use, or omit to determine and increment automatically
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function incrementName($name, $num = null) {
|
||||||
|
|
||||||
|
list($namePrefix, $n) = $this->nameAndNumber($name);
|
||||||
|
|
||||||
|
if($namePrefix !== $name) {
|
||||||
|
if($num) {
|
||||||
|
$num = (int) $num;
|
||||||
|
$name = $namePrefix . $this->delimiter . $num;
|
||||||
|
} else {
|
||||||
|
$zeros = '';
|
||||||
|
while(strpos($name, $namePrefix . $this->delimiter . "0$zeros") === 0) $zeros .= '0';
|
||||||
|
$name = $namePrefix . $this->delimiter . $zeros . (++$n);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(!is_int($num)) $num = 1;
|
||||||
|
$name = $namePrefix . $this->delimiter . $num;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->adjustNameLength($name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is the given name is use by a page?
|
||||||
|
*
|
||||||
|
* @param string $name
|
||||||
|
* @param array $options
|
||||||
|
* - `page` (Page|int): Ignore this Page or page ID
|
||||||
|
* - `parent` (Page|int): Limit search to only this parent.
|
||||||
|
* - `multilang` (bool): Check other languages if multi-language page names supported? (default=false)
|
||||||
|
* - `language` (Language|int): Limit check to only this language (default=null)
|
||||||
|
*
|
||||||
|
* @return int Returns quantity of pages using name, or 0 if name not in use.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function pageNameExists($name, array $options = array()) {
|
||||||
|
|
||||||
|
$defaults = array(
|
||||||
|
'page' => null,
|
||||||
|
'parent' => null,
|
||||||
|
'language' => null,
|
||||||
|
'multilang' => false,
|
||||||
|
);
|
||||||
|
|
||||||
|
$options = array_merge($defaults, $options);
|
||||||
|
$languages = $options['multilang'] || $options['language'] ? $this->wire('languages') : null;
|
||||||
|
if($languages && !$this->wire('modules')->isInstalled('LanguageSupportPageNames')) $languages = null;
|
||||||
|
|
||||||
|
$wheres = array();
|
||||||
|
$binds = array();
|
||||||
|
$parentID = $options['parent'] === null ? null : (int) "$options[parent]";
|
||||||
|
$pageID = $options['page'] === null ? null : (int) "$options[page]";
|
||||||
|
|
||||||
|
if($languages) {
|
||||||
|
foreach($languages as $language) {
|
||||||
|
if($options['language'] && "$options[language]" !== "$language") continue;
|
||||||
|
$property = $language->isDefault() ? 'name' : 'name' . (int) $language->id;
|
||||||
|
$wheres[] = "$property=:name$language->id";
|
||||||
|
$binds[":name$language->id"] = $name;
|
||||||
|
}
|
||||||
|
$wheres = array('(' . implode(' OR ', $wheres) . ')');
|
||||||
|
} else {
|
||||||
|
$wheres[] = 'name=:name';
|
||||||
|
$binds[':name'] = $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if($parentID) {
|
||||||
|
$wheres[] = 'parent_id=:parent_id';
|
||||||
|
$binds[':parent_id'] = $parentID;
|
||||||
|
}
|
||||||
|
if($pageID) {
|
||||||
|
$wheres[] = 'id!=:id';
|
||||||
|
$binds[':id'] = $pageID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$sql = 'SELECT COUNT(*) FROM pages WHERE ' . implode(' AND ', $wheres);
|
||||||
|
$query = $this->wire('database')->prepare($sql);
|
||||||
|
|
||||||
|
foreach($binds as $key => $value) {
|
||||||
|
$query->bindValue($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->execute();
|
||||||
|
$qty = (int) $query->fetchColumn();
|
||||||
|
$query->closeCursor();
|
||||||
|
|
||||||
|
return $qty;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a random, globally unique page name
|
||||||
|
*
|
||||||
|
* @param array $options
|
||||||
|
* - `page` (Page): If name is or should be assigned to a Page, specify it here. (default=null)
|
||||||
|
* - `length` (int): Required/fixed length, or omit for random length (default=0).
|
||||||
|
* - `min` (int): Minimum required length, if fixed length not specified (default=6).
|
||||||
|
* - `max` (int): Maximum allowed length, if fixed length not specified (default=min*2).
|
||||||
|
* - `alpha` (bool): Include alpha a-z letters? (default=true)
|
||||||
|
* - `numeric` (bool): Include numeric digits 0-9? (default=true)
|
||||||
|
* - `confirm` (bool): Confirm that name is globally unique? (default=true)
|
||||||
|
* - `parent` (Page|int): If specified, name must only be unique for this parent Page or ID (default=0).
|
||||||
|
* - `prefix` (string): Prepend this prefix to page name (default='').
|
||||||
|
* - `suffix` (string): Append this suffix to page name (default='').
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function uniqueRandomPageName($options = array()) {
|
||||||
|
|
||||||
|
$defaults = array(
|
||||||
|
'page' => null,
|
||||||
|
'length' => 0,
|
||||||
|
'min' => 6,
|
||||||
|
'max' => 0,
|
||||||
|
'alpha' => true,
|
||||||
|
'numeric' => true,
|
||||||
|
'confirm' => true,
|
||||||
|
'parent' => 0,
|
||||||
|
'prefix' => '',
|
||||||
|
'suffix' => '',
|
||||||
|
);
|
||||||
|
|
||||||
|
if(is_int($options)) $options = array('length' => $options);
|
||||||
|
$options = array_merge($defaults, $options);
|
||||||
|
$rand = new WireRandom();
|
||||||
|
$this->wire($rand);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if($options['length'] < 1) {
|
||||||
|
if($options['min'] < 1) $options['min'] = 6;
|
||||||
|
if($options['max'] < $options['min']) $options['max'] = $options['min'] * 2;
|
||||||
|
if($options['min'] == $options['max']) {
|
||||||
|
$length = $options['max'];
|
||||||
|
} else {
|
||||||
|
$length = mt_rand($options['min'], $options['max']);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$length = (int) $options['length'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if($options['alpha'] && $options['numeric']) {
|
||||||
|
$name = $rand->alphanumeric($length, array('upper' => false, 'noStart' => '0123456789'));
|
||||||
|
} else if($options['numeric']) {
|
||||||
|
$name = $rand->numeric($length);
|
||||||
|
} else {
|
||||||
|
$name = $rand->alpha($length);
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $options['prefix'] . $name . $options['suffix'];
|
||||||
|
|
||||||
|
if($options['confirm']) {
|
||||||
|
$qty = $this->pageNameExists($name, array('page' => $options['page']));
|
||||||
|
} else {
|
||||||
|
$qty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} while($qty);
|
||||||
|
|
||||||
|
if($options['page'] instanceof Page) $options['page']->set('name', $name);
|
||||||
|
|
||||||
|
return $name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the untitled page name string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function untitledPageName() {
|
||||||
|
return $this->untitledPageName;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -2264,6 +2264,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
$page = $this->masterPage ? $this->masterPage : $this->page;
|
$page = $this->masterPage ? $this->masterPage : $this->page;
|
||||||
$parent = $page->parent;
|
$parent = $page->parent;
|
||||||
$parentEditable = ($parent->id && $parent->editable());
|
$parentEditable = ($parent->id && $parent->editable());
|
||||||
|
/** @var Config $config */
|
||||||
|
$config = $this->wire('config');
|
||||||
|
|
||||||
// current page template is assumed, otherwise we wouldn't be here
|
// current page template is assumed, otherwise we wouldn't be here
|
||||||
$templates[$page->template->id] = $page->template;
|
$templates[$page->template->id] = $page->template;
|
||||||
@@ -2283,9 +2285,9 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
|
|
||||||
if($template->flags & Template::flagSystem) {
|
if($template->flags & Template::flagSystem) {
|
||||||
// if($template->name == 'user' && $parent->id != $this->config->usersPageID) continue;
|
// if($template->name == 'user' && $parent->id != $this->config->usersPageID) continue;
|
||||||
if(in_array($template->id, $this->config->userTemplateIDs) && !in_array($parent->id, $this->config->usersPageIDs)) continue;
|
if(in_array($template->id, $config->userTemplateIDs) && !in_array($parent->id, $config->usersPageIDs)) continue;
|
||||||
if($template->name == 'role' && $parent->id != $this->config->rolesPageID) continue;
|
if($template->name == 'role' && $parent->id != $config->rolesPageID) continue;
|
||||||
if($template->name == 'permission' && $parent->id != $this->config->permissionsPageID) continue;
|
if($template->name == 'permission' && $parent->id != $config->permissionsPageID) continue;
|
||||||
if(strpos($template->name, 'repeater_') === 0 || strpos($template->name, 'fieldset_') === 0) continue;
|
if(strpos($template->name, 'repeater_') === 0 || strpos($template->name, 'fieldset_') === 0) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2300,17 +2302,16 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
if(!in_array($template->id, $parent->template->childTemplates)) continue;
|
if(!in_array($template->id, $parent->template->childTemplates)) continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($isSuperuser) {
|
if($template->noParents == -1 && $template->getNumPages() > 0) {
|
||||||
$templates[$template->id] = $template;
|
|
||||||
|
|
||||||
} else if($template->noParents == -1) {
|
|
||||||
// only one of these is allowed to exist
|
// only one of these is allowed to exist
|
||||||
if($template->getNumPages() > 0) continue;
|
continue;
|
||||||
|
|
||||||
} else if($template->noParents) {
|
} else if($template->noParents) {
|
||||||
// user can't change to a template that has been specified as no more instances allowed
|
// user can't change to a template that has been specified as no more instances allowed
|
||||||
// except for superuser... we'll let them do it
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
} else if($isSuperuser) {
|
||||||
|
$templates[$template->id] = $template;
|
||||||
|
|
||||||
} else if((!$template->useRoles && $parentEditable) || $user->hasPermission('page-edit', $template)) {
|
} else if((!$template->useRoles && $parentEditable) || $user->hasPermission('page-edit', $template)) {
|
||||||
// determine if the template's assigned roles match up with the users's roles
|
// determine if the template's assigned roles match up with the users's roles
|
||||||
@@ -2568,14 +2569,23 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
*/
|
*/
|
||||||
public function setupHeadline() {
|
public function setupHeadline() {
|
||||||
|
|
||||||
|
$titlePage = null;
|
||||||
|
|
||||||
if($this->page && $this->page->id) {
|
if($this->page && $this->page->id) {
|
||||||
$page = $this->page;
|
$page = $this->page;
|
||||||
$title = $page->get('title|name');
|
$title = $page->get('title');
|
||||||
|
if(empty($title)) {
|
||||||
|
if($this->wire('pages')->names()->isUntitledPageName($page->name)) {
|
||||||
|
$title = $page->template->getLabel();
|
||||||
|
} else {
|
||||||
|
$title = $page->get('name');
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if($this->parent && $this->parent->id) {
|
} else if($this->parent && $this->parent->id) {
|
||||||
$page = $this->parent;
|
$titlePage = $this->parent;
|
||||||
$title = rtrim($this->parent->path, '/') . '/[...]';
|
$title = rtrim($this->parent->path, '/') . '/[...]';
|
||||||
} else {
|
} else {
|
||||||
$page = new NullPage();
|
$titlePage = new NullPage();
|
||||||
$title = '[...]';
|
$title = '[...]';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2592,8 +2602,12 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
|||||||
$headline = implode(', ', $labels);
|
$headline = implode(', ', $labels);
|
||||||
}
|
}
|
||||||
$browserTitle .= " ($headline)";
|
$browserTitle .= " ($headline)";
|
||||||
|
|
||||||
|
} else if($titlePage) {
|
||||||
|
$headline = $titlePage->get('title|name');
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$headline = $page->get("title|name");
|
$headline = $title;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->headline($headline);
|
$this->headline($headline);
|
||||||
|
Reference in New Issue
Block a user