1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-29 09:29:55 +02:00

12 Commits

Author SHA1 Message Date
Ryan Cramer
2ea60ee7d5 README updates and bump version to 3.0.227 2023-09-12 10:59:21 -04:00
Ryan Cramer
41adc02373 Various minor code and phpdoc updates in several classes 2023-09-11 12:12:56 -04:00
Ryan Cramer
4bb5dbf4a6 Fix issue processwire/processwire-issues#1809 2023-09-11 10:42:43 -04:00
Ryan Cramer
013231acda Additional updates for processwire/processwire-issues#1791 admin asset file version urlsj 2023-09-11 10:21:07 -04:00
Ryan Cramer
7dc8ddc9af Add $config->versionUrls() method for versioned file URLs and update the admin themes to use it 2023-09-08 11:58:38 -04:00
Ryan Cramer
deccd2c8eb Refactor and improve $datetime->elapsedTimeStr() method to add new features and fix the plural issue. Also adds feature requested in processwire/processwire-issues#1328 2023-09-08 10:29:24 -04:00
Ryan Cramer
5b76d4e340 Fix issue processwire/processwire-issues#1808 2023-09-07 10:29:44 -04:00
Ryan Cramer
6df11e5e46 Fix issue processwire/processwire-issues#1805 2023-09-07 09:39:12 -04:00
Ryan Cramer
7ed74281ad Add suggestion from processwire/processwire-issues#1806 2023-09-07 08:35:01 -04:00
Ryan Cramer
b824f645a9 Fix issue where Lister wasn't 100% width in AdminThemeDefault or AdminThemeReno. Note that we had to disable the resizable columns in default/reno admin themes to fix it, as the current version of jquery-tablesorter-resizable doesn't seem to allow for full width tables unless you drag it to be full width. 2023-09-04 11:02:46 -04:00
Ryan Cramer
002c2d15db Additional updates for processwire/processwire-issues#1467 2023-09-01 09:35:23 -04:00
Ryan Cramer
fbf2f140a7 Fix issue processwire/processwire-issues#1804 2023-09-01 09:30:56 -04:00
39 changed files with 592 additions and 273 deletions

View File

@@ -129,20 +129,20 @@ replacing your `/wire/` directory with the one from the newer version.
### Pro module version upgrade notes (if applicable) ### Pro module version upgrade notes (if applicable)
- [FormBuilder](https://processwire.com/store/form-builder/) - [FormBuilder](https://processwire.com/store/form-builder/)
version 0.4.0 or newer required, 0.5.2 or newer recommended. version 0.5.3 or newer recommended.
- [ListerPro](https://processwire.com/store/lister-pro/) - [ListerPro](https://processwire.com/store/lister-pro/)
version 1.0.9 or newer required, 1.1.4 or newer recommended. version 1.1.5 or newer recommended.
- [ProFields](https://processwire.com/store/pro-fields/) - [ProFields](https://processwire.com/store/pro-fields/)
the latest versions of all ProFields (10 modules) are recommended. the latest versions of all ProFields (10 modules) are recommended.
- [LoginRegisterPro](https://processwire.com/store/login-register-pro/) - [LoginRegisterPro](https://processwire.com/store/login-register-pro/)
all versions supported but version 5 or newer recommended. version 7 or newer recommended.
- [ProCache](https://processwire.com/store/pro-cache/) - [ProCache](https://processwire.com/store/pro-cache/)
version 3.1.4 or newer required, 4.0.0 or newer recommended. version 4.0.3 or newer recommended. After upgrading, go to your ProCache
After upgrading, go to your ProCache settings in the admin (Setup > ProCache) settings in the admin (Setup > ProCache) and see if it suggests any
and see if it suggests any modifications to your .htaccess file. modifications to your .htaccess file.
- For all other Pro modules not mentioned above (ProMailer, ProDrafts,
ProDevTools, Likes) there are no specific version requirements but we - For all other Pro modules not mentioned above we recommend using the
recommend using the latest available versions when possible. latest available versions when possible.
## Debug Mode ## Debug Mode
@@ -156,12 +156,11 @@ we think you'll find it very handy during development or when resolving issues.
1. Edit this file: `/site/config.php` 1. Edit this file: `/site/config.php`
2. Find this line: `$config->debug = false;` 2. Find this line: `$config->debug = false;`
3. Change the `false` to `true`, like below, and save. 3. Change the `false` to `true` like below, and save.
``` ```
$config->debug = true; $config->debug = true;
``` ```
This can be found near the bottom of the file, or you can add it if not This can be found near the bottom of the file, or you can add it if not
already there. It will make PHP and ProcessWire report all errors, warnings, already there. It will make PHP and ProcessWire report all errors, warnings,
notices, etc. Of course, you'll want to set it back to false once you've notices, etc. Of course, you'll want to set it back to false once you've
@@ -176,10 +175,10 @@ resolved any issues.
* [Sites running ProcessWire](https://processwire.com/sites/) * [Sites running ProcessWire](https://processwire.com/sites/)
* [Subscribe to ProcessWire Weekly email](https://processwire.com/community/newsletter/subscribe/) * [Subscribe to ProcessWire Weekly email](https://processwire.com/community/newsletter/subscribe/)
* [Submit your site to our directory](https://processwire.com/sites/submit/) * [Submit your site to our directory](https://processwire.com/sites/submit/)
* [Follow @processwire on Twitter](http://twitter.com/processwire/) * [Follow @processwire on X-Twitter](http://twitter.com/processwire/)
* [Contact ProcessWire](https://processwire.com/contact/) * [Contact ProcessWire developer](https://processwire.com/contact/)
* [Report issue](https://github.com/processwire/processwire-issues/issues)
------ ------
Copyright 2023 by Ryan Cramer / Ryan Cramer Design, LLC Copyright 2023 by Ryan Cramer / Ryan Cramer Design, LLC

View File

@@ -1,11 +1,15 @@
<?php namespace ProcessWire; <?php namespace ProcessWire;
// Template file for pages using the “basic-page” template // Template file for pages using the “basic-page” template
// -------------------------------------------------------
// The #content div in this file will replace the #content div in _main.php
// when the Markup Regions feature is enabled, as it is by default.
// You can also append to (or prepend to) the #content div, and much more.
// See the Markup Regions documentation:
// https://processwire.com/docs/front-end/output/markup-regions/
?> ?>
<div id="content"> <div id="content">
Basic page content Basic page content
</div> </div>

View File

@@ -1,10 +1,15 @@
<?php namespace ProcessWire; <?php namespace ProcessWire;
// Template file for “home” template used by the homepage // Template file for “home” template used by the homepage
// ------------------------------------------------------
// The #content div in this file will replace the #content div in _main.php
// when the Markup Regions feature is enabled, as it is by default.
// You can also append to (or prepend to) the #content div, and much more.
// See the Markup Regions documentation:
// https://processwire.com/docs/front-end/output/markup-regions/
?> ?>
<div id="content"> <div id="content">
Homepage content Homepage content
</div> </div>

View File

@@ -226,6 +226,36 @@ $config->usePageClasses = false;
*/ */
$config->useLazyLoading = true; $config->useLazyLoading = true;
/**
* Default value for $useVersion argument of $config->versionUrls() method
*
* Controls the cache busting behavior of the `$config->versionUrls()` method as used by
* ProcessWires admin themes (but may be used independently as well). When no
* `$useVersion` argument is specified to the versionUrls() method, it will use the
* default value specified here. If not specified, null is the default.
*
* - `true` (bool): Get version from filemtime.
* - `false` (bool): Never get file version, just use `$config->version`.
* - `foobar` (string): Specify any string to be the version to use on all URLs needing it.
* - `?foo=bar` (string): Optionally specify your own query string variable=value.
* - `null` (null): Auto-detect: use file version in debug mode or dev branch only,
* otherwise use `$config->version`.
*
* ~~~~~
* // choose one to start with, copy and place in /site/config.php to enable
* $config->useVersionUrls = null; // default setting
* $config->useVersionUrls = true; // always use filemtime based version URLs
* $config->useVersionUrls = false; // only use core version in URLs
* $config->versionUrls = 'hello-world'; // always use this string as the version
* $config->versionUrls = '?version=123'; // optionally specify query string var and value
* ~~~~~
*
* @var null|bool|string
* @since 3.0.227
*
* $config->useVersionUrls = null;
*/
/** /**
* Disable all HTTPS requirements? * Disable all HTTPS requirements?
* *
@@ -700,7 +730,7 @@ $config->contentTypes = array(
'txt' => 'text/plain', 'txt' => 'text/plain',
'json' => 'application/json', 'json' => 'application/json',
'xml' => 'application/xml', 'xml' => 'application/xml',
); );
/** /**
* File content types * File content types
@@ -733,7 +763,7 @@ $config->fileContentTypes = array(
'webp' => 'image/webp', 'webp' => 'image/webp',
'zip' => '+application/zip', 'zip' => '+application/zip',
'mp3' => 'audio/mpeg', 'mp3' => 'audio/mpeg',
); );
/** /**
* Named predefined image sizes and options * Named predefined image sizes and options
@@ -797,7 +827,7 @@ $config->imageSizerOptions = array(
'hidpiQuality' => 60, // Same as above quality setting, but specific to hidpi images 'hidpiQuality' => 60, // Same as above quality setting, but specific to hidpi images
'defaultGamma' => 2.0, // defaultGamma: 0.5 to 4.0 or -1 to disable gamma correction (default=2.0) 'defaultGamma' => 2.0, // defaultGamma: 0.5 to 4.0 or -1 to disable gamma correction (default=2.0)
'webpAdd' => false, // set this to true, if the imagesizer engines should create a Webp copy with every (new) image variation 'webpAdd' => false, // set this to true, if the imagesizer engines should create a Webp copy with every (new) image variation
); );
/** /**
* Options for webp images * Options for webp images
@@ -815,7 +845,7 @@ $config->webpOptions = array(
'useSrcExt' => false, // Use source file extension in webp filename? (file.jpg.webp rather than file.webp) 'useSrcExt' => false, // Use source file extension in webp filename? (file.jpg.webp rather than file.webp)
'useSrcUrlOnSize' => true, // Fallback to source file URL when webp file is larger than source? 'useSrcUrlOnSize' => true, // Fallback to source file URL when webp file is larger than source?
'useSrcUrlOnFail' => true, // Fallback to source file URL when webp file fails for some reason? 'useSrcUrlOnFail' => true, // Fallback to source file URL when webp file fails for some reason?
); );
/** /**
* Admin thumbnail image options * Admin thumbnail image options
@@ -846,7 +876,7 @@ $config->adminThumbOptions = array(
'sharpening' => 'soft', // sharpening: none | soft | medium | strong 'sharpening' => 'soft', // sharpening: none | soft | medium | strong
'quality' => 90, 'quality' => 90,
'suffix' => '', 'suffix' => '',
); );
/** /**
* File compiler options (as used by FileCompiler class) * File compiler options (as used by FileCompiler class)
@@ -875,7 +905,7 @@ $config->fileCompilerOptions = array(
'exclusions' => array(), // exclude filenames or paths that start with any of these 'exclusions' => array(), // exclude filenames or paths that start with any of these
'extensions' => array('php', 'module', 'inc'), // file extensions we compile 'extensions' => array('php', 'module', 'inc'), // file extensions we compile
'cachePath' => '', // path where compiled files are stored, or blank for $config->paths->cache . 'FileCompiler/' 'cachePath' => '', // path where compiled files are stored, or blank for $config->paths->cache . 'FileCompiler/'
); );
/** /**
* Temporary directory for uploads * Temporary directory for uploads

View File

@@ -151,6 +151,7 @@
* @property bool $useMarkupRegions Enable support for front-end markup regions? #pw-group-system * @property bool $useMarkupRegions Enable support for front-end markup regions? #pw-group-system
* @property bool|array $useLazyLoading Delay loading of fields (and templates/fieldgroups) till requested? Can improve performance on systems with lots of fields or templates. #pw-group-system @since 3.0.193 * @property bool|array $useLazyLoading Delay loading of fields (and templates/fieldgroups) till requested? Can improve performance on systems with lots of fields or templates. #pw-group-system @since 3.0.193
* @property bool $usePageClasses Use custom Page classes in `/site/classes/[TemplateName]Page.php`? #pw-group-system @since 3.0.152 * @property bool $usePageClasses Use custom Page classes in `/site/classes/[TemplateName]Page.php`? #pw-group-system @since 3.0.152
* @property bool|int|string|null $useVersionUrls Default value for $useVersion argument of $config->versionUrls() method #pw-group-system @since 3.0.227
* @property int $lazyPageChunkSize Chunk size for for $pages->findMany() calls. #pw-group-system * @property int $lazyPageChunkSize Chunk size for for $pages->findMany() calls. #pw-group-system
* *
* @property string $userAuthSalt Salt generated at install time to be used as a secondary/non-database salt for the password system. #pw-group-session * @property string $userAuthSalt Salt generated at install time to be used as a secondary/non-database salt for the password system. #pw-group-session
@@ -948,10 +949,134 @@ class Config extends WireData {
*/ */
public function setWire(ProcessWire $wire) { public function setWire(ProcessWire $wire) {
parent::setWire($wire); parent::setWire($wire);
$paths = $this->paths; foreach(array('paths', 'urls', 'styles', 'scripts') as $key) {
if($paths) $paths->setWire($wire); $value = $this->get($key);
$urls = $this->urls; if($value instanceof Wire) $value->setWire($wire);
if($urls) $urls->setWire($wire); }
} }
}
/**
* Given array of file asset URLs return them with cache-busting version strings
*
* URLs that aready have query strings or URLs with scheme (i.e. https://) are ignored,
* except for URLs that already have a core version query string, i.e. `?v=3.0.227`
* may be converted to a different version string when appropriate.
*
* URLs that do not resolve to a physical file on the file system, relative URLs, or
* URLs that are outside of ProcessWires web root, are only eligible to receive a
* common/shared version in the URL (like the core version).
*
* To set a different default value for the `$useVersion` argument, you can populate
* the `$config->useVersionUrls` setting in your /site/config.php with the default
* value you want to substitute.
*
* ~~~~~
* foreach($config->versionUrls($config->styles) as $url) {
* echo "<link rel='stylesheet' href='$url' />";
* }
* // there is also this shortcut for the above
* foreach($config->styles->urls() as $url) {
* echo "<link rel='stylesheet' href='$url' />";
* }
* ~~~~~
*
* #pw-group-URLs
* #pw-group-tools
*
* @param array|FilenameArray|WireArray|\ArrayObject $urls Array of URLs to file assets such as JS/CSS files.
* @param bool|null|string $useVersion What to use for the version string (`null` is default):
* - `true` (bool): Get version from filemtime.
* - `false` (bool): Never get file version, just use $config->version.
* - `null` (null): Auto-detect: use file version in debug mode or dev branch only, $config->version otherwise.
* - `foobar` (string): Specify any string to be the version to use on all URLs needing it.
* `- ?foo=bar` (string): Optionally specify your own query string variable=value.
* - The default value (null) can be overridden by the `$config->useVersionUrls` setting.
* @return array Array of URLs updated with version strings where needed
* @since 3.0.227
*
*/
public function versionUrls($urls, $useVersion = null) {
$a = array();
$rootUrl = $this->urls->root;
$rootPath = $this->paths->root;
$coreVersionStr = "?v=$this->version";
if($useVersion === null) {
// if useVersion argument not specified pull from $config->useVersionUrls
$useVersion = $this->useVersionUrls;
if($useVersion === null) {
// if null or still not specified, auto-detect what to use
$useVersion = ($this->debug || ProcessWire::versionSuffix === 'dev');
}
}
if(is_string($useVersion)) {
// custom version string specified
if(!ctype_alnum(str_replace(array('.', '-', '_', '?', '='), '', $useVersion))) {
// if it fails sanitization then fallback to core version
$useVersion = false;
$versionStr = $coreVersionStr;
} else {
// use custom version str
$versionStr = $useVersion;
if(strpos($versionStr, '?') === false) $versionStr = "?v=$versionStr";
}
} else {
// use core version when appropriate
$versionStr = $coreVersionStr;
}
foreach($urls as $url) {
if(strpos($url, $coreVersionStr)) {
// url already has core version present in it
if($useVersion === false) {
// use as-is since this is already what's requested
$a[] = $url;
continue;
}
// remove existing core-version query string
list($u, $r) = explode($coreVersionStr, $url, 2);
if(!strlen($r)) $url = $u;
}
if(strpos($url, '?') !== false || strpos($url, '//') !== false) {
// leave URL with query string or scheme:// alone
$a[] = $url;
} else if($useVersion === true && strpos($url, $rootUrl) === 0) {
// use filemtime based version
$f = $rootPath . substr($url, strlen($rootUrl));
if(is_readable($f)) {
$a[] = "$url?" . base_convert((int) filemtime($f), 10, 36);
} else {
$a[] = $url . $versionStr;
}
} else {
// use standard or specified versino string
$a[] = $url . $versionStr;
}
}
return $a;
}
/**
* Given a file asset URLs return it with cache-busting version string
*
* URLs that aready have query strings are left alone.
*
* #pw-group-URLs
* #pw-group-tools
*
* @param string $url URL to a file asset (such as JS/CSS file)
* @param bool|null|string $useVersion See versionUrls() method for description of this argument.
* @return string URL updated with version strings where necessary
* @since 3.0.227
* @see Config::versionUrls()
*
*/
public function versionUrl($url, $useVersion = null) {
$a = $this->versionUrls(array($url), $useVersion);
return isset($a[0]) ? $a[0] : $url;
}
}

View File

@@ -10,7 +10,7 @@
* *
*/ */
class FilenameArray implements \IteratorAggregate, \Countable { class FilenameArray extends Wire implements \IteratorAggregate, \Countable {
/** /**
* Array of filenames indexed by MD5 hash of filename * Array of filenames indexed by MD5 hash of filename
@@ -87,6 +87,23 @@ class FilenameArray implements \IteratorAggregate, \Countable {
return new \ArrayObject($this->data); return new \ArrayObject($this->data);
} }
/**
* Get cache-busting URLs for this FilenameArray
*
* This is the same as iterating this FilenameArray except that it appends cache-busting
* query strings to the URLs that resolve to physical files.
*
* @param bool|null|string $useVersion See Config::versionUrls() for arument details
* @return array
* @throws WireException
* @see Config::versionUrls()
* @since 3.0.227
*
*/
public function urls($useVersion = null) {
return $this->wire()->config->versionUrls($this, $useVersion);
}
/** /**
* Make FilenameArray unique (deprecated) * Make FilenameArray unique (deprecated)
* *

View File

@@ -863,7 +863,7 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
// wrap the inputfield output // wrap the inputfield output
$attrs = ''; $attrs = '';
$label = $inputfield->getSetting('label'); $label = (string) $inputfield->getSetting('label');
$skipLabel = $inputfield->getSetting('skipLabel'); $skipLabel = $inputfield->getSetting('skipLabel');
$skipLabel = is_bool($skipLabel) || empty($skipLabel) ? (bool) $skipLabel : (int) $skipLabel; // force as bool or int $skipLabel = is_bool($skipLabel) || empty($skipLabel) ? (bool) $skipLabel : (int) $skipLabel; // force as bool or int
if(!strlen($label) && $skipLabel !== Inputfield::skipLabelBlank && $inputfield->className() != 'InputfieldWrapper') { if(!strlen($label) && $skipLabel !== Inputfield::skipLabelBlank && $inputfield->className() != 'InputfieldWrapper') {
@@ -1954,4 +1954,3 @@ class InputfieldWrapper extends Inputfield implements \Countable, \IteratorAggre
} }
} }

View File

@@ -650,13 +650,14 @@ class PageTraversal {
$options['pageNum'] = $input->pageNum(); $options['pageNum'] = $input->pageNum();
} }
if(count($options['urlSegments'])) { if(is_array($options['urlSegments']) && count($options['urlSegments'])) {
$str = ''; $str = '';
if(is_string($options['urlSegments'][0])) { reset($options['urlSegments']);
if(is_string(key($options['urlSegments']))) {
// associative array converts to key/value style URL segments // associative array converts to key/value style URL segments
foreach($options['urlSegments'] as $key => $value) { foreach($options['urlSegments'] as $key => $value) {
$str .= "$key/$value/"; $str .= "$key/$value/";
if(is_int($key)) $str = ''; if(is_int($key)) $str = ''; // abort assoc array option if any int key found
if($str === '') break; if($str === '') break;
} }
} }

View File

@@ -79,7 +79,7 @@ class ProcessWire extends Wire {
* Reversion revision number * Reversion revision number
* *
*/ */
const versionRevision = 226; const versionRevision = 227;
/** /**
* Version suffix string (when applicable) * Version suffix string (when applicable)

View File

@@ -663,17 +663,44 @@ class WireDateTime extends Wire {
/** /**
* Render an elapsed time string * Render an elapsed time string
* *
* If the `$stop` argument is omitted then it is assumed to be the current time.
* The maximum period used is weeks, as months and years are not fixed length periods.
*
* ~~~~~
* $start = '2023-09-08 08:33:52';
* $stop = '2023-09-09 10:47:23';
*
* // Regular: 1 day 2 hours 13 minutes 31 seconds
* echo $datetime->elapsedTimeStr($start, $stop);
*
* // Abbreviated: 1 day 2 hrs 13 mins 31 secs
* echo $datetime->elapsedTimeStr($start, $stop, true);
*
* // Abbreviated with exclusions: 1 day 2 hrs
* echo $datetime->elapsedTimeStr($start, $stop, true, [ 'exclude' => 'minutes seconds' ]);
*
* // Optional 3.0.227+ usage and inclusions: 26 hours 13 minutes
* echo $datetime->elapsedTimeStr($start, [ 'stop' => $stop, 'include' => 'hours minutes' ]);
* ~~~~~
*
* @param int|string $start Starting timestamp or date/time string. * @param int|string $start Starting timestamp or date/time string.
* @param int|string $stop Ending timestamp or date/time string, or omit for now. * @param int|string|array $stop Ending timestamp or date/time string, omit for now”, or:
* - In 3.0.227+ you may optionally substitute the `$options` array argument here. When doing so,
* all remaining arguments are ignored and the `stop` and `abbreviate` (if needed) may be
* specified in the given options array, along with any other options.
* @param bool|int|array $abbreviate * @param bool|int|array $abbreviate
* - Specify boolean FALSE for verbose elapsed time string without abbreviations (default). * - Specify boolean FALSE for verbose elapsed time string without abbreviations (default).
* - Specify boolean TRUE for abbreviations (abbreviated where common, not always different from non-abbreviated). * - Specify boolean TRUE for abbreviations (abbreviated where common, not always different from non-abbreviated).
* - Specify integer 1 for extra short abbreviations (all terms abbreviated into shortest possible string). * - Specify integer `1` for extra short abbreviations (all terms abbreviated into shortest possible string).
* - Specify integer 0 for digital elapsed time string like “00:01:12” referring to hours:minutes:seconds. * - Specify integer `0` for digital elapsed time string like “00:01:12” referring to hours:minutes:seconds.
* - Note that when using `0` no options apply except except for `exclude[seconds]` option.
* @param array $options Additional options: * @param array $options Additional options:
* - `delimiter` (string): String to separate time periods (default=' '). * - `delimiter` (string): String to separate time periods (default=' ').
* - `getArray` (bool): Return an array of integers indexed by period name (rather than a string)? 3.0.227+
* - `exclude` (array|string): Exclude these periods, one or more of: 'seconds', 'minutes', 'hours', 'days', 'weeks' (default=[]) * - `exclude` (array|string): Exclude these periods, one or more of: 'seconds', 'minutes', 'hours', 'days', 'weeks' (default=[])
* @return string * - `include` (array|string): Include only these periods, one or more of: 'seconds', 'minutes', 'hours', 'days', 'weeks' (default=[]) 3.0.227+
* - Note the exclude and include options should not be used together, and the include option requires 3.0.227+.
* @return string|array Returns array only if the `getArray` option is true, otherwise returns a string.
* @since 3.0.129 * @since 3.0.129
* *
*/ */
@@ -682,72 +709,131 @@ class WireDateTime extends Wire {
$defaults = array( $defaults = array(
'delimiter' => ' ', 'delimiter' => ' ',
'exclude' => array(), 'exclude' => array(),
'include' => array(),
'getArray' => false,
); );
if(is_array($stop)) {
// options specified in $stop argument
$options = $stop;
$stop = isset($options['stop']) ? $options['stop'] : null;
$abbreviate = isset($options['abbreviate']) ? $options['abbreviate'] : false;
}
$options = array_merge($defaults, $options); $options = array_merge($defaults, $options);
if(is_string($options['exclude'])) $options['exclude'] = explode(' ', $options['exclude']); $periodNames = array('weeks', 'days', 'hours', 'minutes', 'seconds');
$usePeriods = array();
$negative = false;
foreach(array('exclude', 'include') as $key) {
if(is_string($options[$key])) {
$value = trim($options[$key]);
$options[$key] = $value ? explode(' ', $value) : array();
} else if(!is_array($options[$key])) {
$options[$key] = array();
}
foreach($options[$key] as $k => $v) {
if(!in_array($v, $periodNames)) unset($options[$key][$k]);
}
}
$include = count($options['include']) && $abbreviate !== 0 ? $options['include'] : null;
$exclude = count($options['exclude']) ? $options['exclude'] : null;
foreach($periodNames as $name) {
if($include && !in_array($name, $include)) continue;
if($exclude && in_array($name, $exclude)) continue;
$usePeriods[$name] = $name;
}
if($stop === null) $stop = time(); if($stop === null) $stop = time();
if(!ctype_digit("$start")) $start = strtotime($start); if(!ctype_digit("$start")) $start = strtotime($start);
if(!ctype_digit("$stop")) $stop = strtotime($stop); if(!ctype_digit("$stop")) $stop = strtotime($stop);
if($start > $stop) {
list($start, $stop) = array($stop, $start);
$negative = true;
}
$times = array(); $times = array();
$seconds = $stop - $start; $seconds = $stop - $start;
if($seconds >= 604800 && $abbreviate !== 0 && !in_array('weeks', $options['exclude'])) { if($seconds >= 604800 && $abbreviate !== 0 && isset($usePeriods['weeks'])) {
$weeks = floor($seconds / 604800); $weeks = floor($seconds / 604800);
$seconds = $seconds - ($weeks * 604800); $seconds = $seconds - ($weeks * 604800);
$key = $weeks === 1 ? 'week' : 'weeks'; $key = $weeks == 1 ? 'week' : 'weeks';
$times[$key] = $weeks; $times[$key] = $weeks;
} } else {
$times['weeks'] = 0;
if($seconds >= 86400 && $abbreviate !== 0 && !in_array('days', $options['exclude'])) {
$days = floor($seconds / 86400);
$seconds = $seconds - ($days * 86400);
$key = $days === 1 ? 'day' : 'days';
$times[$key] = $days;
} }
if($seconds >= 3600 && !in_array('hours', $options['exclude'])) { if($seconds >= 86400 && $abbreviate !== 0 && isset($usePeriods['days'])) {
$days = floor($seconds / 86400);
$seconds = $seconds - ($days * 86400);
$key = $days == 1 ? 'day' : 'days';
$times[$key] = $days;
} else {
$times['days'] = 0;
}
if($seconds >= 3600 && isset($usePeriods['hours'])) {
$hours = floor($seconds / 3600); $hours = floor($seconds / 3600);
$seconds = $seconds - ($hours * 3600); $seconds = $seconds - ($hours * 3600);
$key = $hours === 1 ? 'hour' : 'hours'; $key = $hours == 1 ? 'hour' : 'hours';
$times[$key] = $hours; $times[$key] = $hours;
} else { } else {
$times['hours'] = 0;
$hours = 0; $hours = 0;
} }
if($seconds >= 60 && !in_array('minutes', $options['exclude'])) { if($seconds >= 60 && isset($usePeriods['minutes'])) {
$minutes = floor($seconds / 60); $minutes = floor($seconds / 60);
$seconds = $seconds - ($minutes * 60); $seconds = $seconds - ($minutes * 60);
$key = $minutes === 1 ? 'minute' : 'minutes'; $key = $minutes == 1 ? 'minute' : 'minutes';
$times[$key] = $minutes; $times[$key] = $minutes;
} else { } else {
$times['minutes'] = 0;
$minutes = 0; $minutes = 0;
} }
if(($seconds > 0 || empty($times)) && !in_array('seconds', $options['exclude'])) { if(($seconds > 0 || empty($times)) && isset($usePeriods['seconds'])) {
$key = $seconds === 1 ? 'second' : 'seconds'; $key = $seconds == 1 ? 'second' : 'seconds';
$times[$key] = $seconds; $times[$key] = $seconds;
} else { } else {
$times['seconds'] = 0;
$seconds = 0; $seconds = 0;
} }
if($abbreviate === 0) { if($abbreviate === 0 && !$options['getArray']) {
if(strlen($hours) < 2) $hours = "0$hours"; if(strlen($hours) < 2) $hours = "0$hours";
if(strlen($minutes) < 2) $minutes = "0$minutes"; if(strlen($minutes) < 2) $minutes = "0$minutes";
if(strlen($seconds) < 2) $seconds = "0$seconds"; if(strlen($seconds) < 2) $seconds = "0$seconds";
$str = "$hours:$minutes:$seconds"; $value = "$hours:$minutes";
if(isset($usePeriods['seconds'])) $value .= ":$seconds";
} else { } else {
$periods = $this->getPeriods($abbreviate); $periods = $this->getPeriods($abbreviate);
$a = array(); $a = array();
$getArray = array();
foreach($times as $key => $qty) { foreach($times as $key => $qty) {
$pluralKey = rtrim($key, 's') . 's';
if(empty($qty) && ($pluralKey !== 'seconds' || count($a))) continue;
if(!isset($usePeriods[$pluralKey])) continue;
$sep = $abbreviate === 1 ? '' : ' '; $sep = $abbreviate === 1 ? '' : ' ';
$a[] = $qty . $sep . $periods[$key]; $str = $qty . $sep . $periods[$key];
$a[] = $str;
$getArray[$pluralKey] = $qty;
$getArray[$pluralKey . 'Text'] = $str;
}
$value = implode($options['delimiter'], $a);
if($negative) $value = "-$value";
if($options['getArray']) {
$getArray['negative'] = $negative;
$getArray['text'] = $value;
$value = $getArray;
} }
$str = implode($options['delimiter'], $a);
} }
return $str; return $value;
} }
/** /**

View File

@@ -5,7 +5,7 @@
* *
* Supportings finding and manipulating of markup regions in an HTML document. * Supportings finding and manipulating of markup regions in an HTML document.
* *
* ProcessWire 3.x, Copyright 2017 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
*/ */
@@ -277,7 +277,7 @@ class WireMarkupRegions extends Wire {
if(!empty($options['leftover'])) { if(!empty($options['leftover'])) {
if(!empty($leftover)) { if(!empty($leftover)) {
foreach($regions as $key => $region) { foreach($regions as $region) {
if(strpos($leftover, $region['html']) !== false) { if(strpos($leftover, $region['html']) !== false) {
$leftover = str_replace($region['html'], '', $leftover); $leftover = str_replace($region['html'], '', $leftover);
} }
@@ -340,7 +340,7 @@ class WireMarkupRegions extends Wire {
if(strpos($find, '.') > 0) { if(strpos($find, '.') > 0) {
// i.e. "div.myclass" // i.e. "div.myclass"
list($findTag, $_find) = explode('.', $find, 2); list($findTag, $_find) = explode('.', $find, 2);
if($this->wire('sanitizer')->alphanumeric($findTag) === $findTag) { if($this->wire()->sanitizer->alphanumeric($findTag) === $findTag) {
$find = ".$_find"; $find = ".$_find";
} else { } else {
$findTag = ''; $findTag = '';
@@ -997,14 +997,15 @@ class WireMarkupRegions extends Wire {
* *
*/ */
public function renderAttributes(array $attrs, $encode = true, $quote = '"') { public function renderAttributes(array $attrs, $encode = true, $quote = '"') {
$sanitizer = $this->wire()->sanitizer;
$str = ''; $str = '';
foreach($attrs as $name => $value) { foreach($attrs as $name => $value) {
if(!ctype_alnum($name)) { if(!ctype_alnum($name)) {
// only allow [-_a-zA-Z] attribute names // only allow [-_a-zA-Z] attribute names
$name = $this->wire('sanitizer')->name($name); $name = $sanitizer->name($name);
} }
// convert arrays to space separated string // convert arrays to space separated string
@@ -1023,7 +1024,7 @@ class WireMarkupRegions extends Wire {
if($encode) { if($encode) {
// entity encode value // entity encode value
$value = $this->wire('sanitizer')->entities($value); $value = $sanitizer->entities($value);
} else if(strpos($value, '"') !== false && strpos($value, "'") === false) { } else if(strpos($value, '"') !== false && strpos($value, "'") === false) {
// if value has a quote in it, use single quotes rather than double quotes // if value has a quote in it, use single quotes rather than double quotes
@@ -1358,7 +1359,7 @@ class WireMarkupRegions extends Wire {
$options = array_merge($defaults, $options); $options = array_merge($defaults, $options);
$leftoverMarkup = ''; $leftoverMarkup = '';
$hasDebugLandmark = strpos($htmlDocument, self::debugLandmark) !== false; $hasDebugLandmark = strpos($htmlDocument, self::debugLandmark) !== false;
$debug = $hasDebugLandmark && $this->wire('config')->debug; $debug = $hasDebugLandmark && $this->wire()->config->debug;
$debugTimer = $debug ? Debug::timer() : 0; $debugTimer = $debug ? Debug::timer() : 0;
if(is_array($htmlRegions)) { if(is_array($htmlRegions)) {
@@ -1398,7 +1399,7 @@ class WireMarkupRegions extends Wire {
$updates = array(); $updates = array();
$numUpdates = 0; $numUpdates = 0;
foreach($regions as $regionKey => $region) { foreach($regions as /* $regionKey => */ $region) {
if(empty($region['action'])) $region['action'] = 'auto'; // replace if(empty($region['action'])) $region['action'] = 'auto'; // replace
if(empty($region['actionTarget'])) $region['actionTarget'] = $region['pwid']; // replace if(empty($region['actionTarget'])) $region['actionTarget'] = $region['pwid']; // replace
@@ -1506,7 +1507,7 @@ class WireMarkupRegions extends Wire {
if(count($this->debugNotes)) { if(count($this->debugNotes)) {
$this->debugNotes = array_unique($this->debugNotes); $this->debugNotes = array_unique($this->debugNotes);
$debugNotes[] = "---------------"; $debugNotes[] = "---------------";
foreach($this->debugNotes as $n => $s) { foreach($this->debugNotes as $s) {
$debugNotes[] = $this->debugNoteStr($s); $debugNotes[] = $this->debugNoteStr($s);
} }
} }
@@ -1630,7 +1631,7 @@ class WireMarkupRegions extends Wire {
if(!count($debugNotes)) $debugNotes[] = "Nothing found"; if(!count($debugNotes)) $debugNotes[] = "Nothing found";
if($debugTimer !== null) $debugNotes[] = '[sm]' . Debug::timer($debugTimer) . ' seconds[/sm]'; if($debugTimer !== null) $debugNotes[] = '[sm]' . Debug::timer($debugTimer) . ' seconds[/sm]';
$out = "" . implode("\n", $debugNotes); $out = "" . implode("\n", $debugNotes);
$out = $this->wire('sanitizer')->entities($out); $out = $this->wire()->sanitizer->entities($out);
$out = str_replace(array('[sm]', '[/sm]'), array('<small style="opacity:0.7">', '</small>'), $out); $out = str_replace(array('[sm]', '[/sm]'), array('<small style="opacity:0.7">', '</small>'), $out);
$out = str_replace(array('[b]', '[/b]'), array('<strong>', '</strong>'), $out); $out = str_replace(array('[b]', '[/b]'), array('<strong>', '</strong>'), $out);
$out = "<pre class='pw-debug pw-region-debug'>$out</pre>" . self::debugLandmark; $out = "<pre class='pw-debug pw-region-debug'>$out</pre>" . self::debugLandmark;
@@ -1643,4 +1644,4 @@ class WireMarkupRegions extends Wire {
$markup = str_replace(self::debugLandmark, $out, $markup); $markup = str_replace(self::debugLandmark, $out, $markup);
} }
} }

View File

@@ -5,7 +5,7 @@
* *
* Includes methods for random strings, numbers, arrays and passwords. * Includes methods for random strings, numbers, arrays and passwords.
* *
* ProcessWire 3.x, Copyright 2018 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @since 3.0.111 * @since 3.0.111
@@ -640,7 +640,7 @@ class WireRandom extends Wire {
$numUpper = $this->integer($options['minUpper'], $options['maxUpper']); $numUpper = $this->integer($options['minUpper'], $options['maxUpper']);
if($numUpper) { if($numUpper) {
$value = strtolower($value); $value = strtolower($value);
$test = $this->wire('sanitizer')->alpha($value); $test = $this->wire()->sanitizer->alpha($value);
if(strlen($test) < $numUpper) { if(strlen($test) < $numUpper) {
// there aren't enough characters present to meet requirements, so add some // there aren't enough characters present to meet requirements, so add some
$value .= $this->alpha($numUpper - strlen($test), array('disallow' => $disallow)); $value .= $this->alpha($numUpper - strlen($test), array('disallow' => $disallow));
@@ -672,7 +672,7 @@ class WireRandom extends Wire {
// manage quantity of required digits // manage quantity of required digits
if($options['minDigits'] > 0) { if($options['minDigits'] > 0) {
$test = $this->wire('sanitizer')->digits($value); $test = $this->wire()->sanitizer->digits($value);
$test = str_replace($options['disallow'], '', $test); $test = str_replace($options['disallow'], '', $test);
$numDigits = $options['minDigits'] - strlen($test); $numDigits = $options['minDigits'] - strlen($test);
if($numDigits > 0) { if($numDigits > 0) {

View File

@@ -59,9 +59,9 @@ $extras = $adminTheme->getExtraMarkup();
<script type="text/javascript"><?php echo $helpers->renderJSConfig(); ?></script> <script type="text/javascript"><?php echo $helpers->renderJSConfig(); ?></script>
<?php foreach($config->styles as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?> <?php foreach($config->styles->urls() as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?>
<?php foreach($config->scripts as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?> <?php foreach($config->scripts->urls() as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?>
<?php echo $extras['head']; ?> <?php echo $extras['head']; ?>

View File

@@ -60,8 +60,8 @@ $extras = $adminTheme->getExtraMarkup();
<title><?php echo $helpers->renderBrowserTitle(); ?></title> <title><?php echo $helpers->renderBrowserTitle(); ?></title>
<script type="text/javascript"><?php echo $helpers->renderJSConfig(); ?></script> <script type="text/javascript"><?php echo $helpers->renderJSConfig(); ?></script>
<?php foreach($config->styles as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?> <?php foreach($config->styles->urls() as $file) echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; ?>
<?php foreach($config->scripts as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?> <?php foreach($config->scripts->urls() as $file) echo "\n\t<script type='text/javascript' src='$file'></script>"; ?>
<?php echo $extras['head']; ?> <?php echo $extras['head']; ?>
</head> </head>

View File

@@ -46,12 +46,12 @@ $scripts->append($themeUrl . "scripts/main.js?v=$version");
</script> </script>
<?php <?php
foreach($styles as $file) { foreach($styles->urls() as $file) {
echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />"; echo "\n\t<link type='text/css' href='$file' rel='stylesheet' />";
} }
if($adminTheme->maxWidth && strpos($layout, 'sidenav') === false) { if($adminTheme->maxWidth && strpos($layout, 'sidenav') === false) {
echo "\n\t<style type='text/css'>.pw-container { max-width: {$adminTheme->maxWidth}px; }</style>"; echo "\n\t<style type='text/css'>.pw-container { max-width: {$adminTheme->maxWidth}px; }</style>";
} }
foreach($scripts as $file) { foreach($scripts->urls() as $file) {
echo "\n\t<script type='text/javascript' src='$file'></script>"; echo "\n\t<script type='text/javascript' src='$file'></script>";
} }

View File

@@ -1754,6 +1754,29 @@ class FieldtypeFile extends FieldtypeMulti implements ConfigurableModule, Fieldt
return $pagefiles; return $pagefiles;
} }
/**
* Called after field renamed
*
* @param Field $field
* @param string $prevName Previous name (current name can be found in $field->name)
*
*/
public function ___renamedField(Field $field, $prevName) {
// if there is a custom-fields template, rename it
$templates = $this->wire()->templates;
if($templates->get("field-$field->name")) return;
if($templates->get("field-x-$field->name")) return;
$template = $templates->get("field-$prevName");
if($template) {
$templates->rename($template, "field-$field->name");
} else {
$template = $templates->get("field-x-$prevName");
if($template) {
$templates->rename($template, "field-x-$field->name");
}
}
}
/** /**
* Field config * Field config
* *

View File

@@ -1326,6 +1326,27 @@ class FieldtypePage extends FieldtypeMulti implements Module, ConfigurableModule
return true; return true;
} }
/**
* Return whether the given value is considered empty or not.
*
* @param Field $field
* @param mixed|Selector $value
* @return bool
*
*/
public function isEmptyValue(Field $field, $value) {
if($value instanceof Selector && $value->field === $field->name) {
// PageFinder is asking if we want to handle this field/value match internally
if($value->operator === '!=' && !empty("$value->value") && !ctype_digit("$value->value")) {
// if a page name (rather than id) is specified with a `!=` operator
// then tell PageFinder that we handle this unique match condition internally
// since the page name has to be converted to page ID by getMatchQuery()
return true;
}
}
return parent::isEmptyValue($field, $value);
}
/** /**
* Return the database schema in predefined format * Return the database schema in predefined format
* *

View File

@@ -8,7 +8,7 @@
* For documentation about the fields used in this class, please see: * For documentation about the fields used in this class, please see:
* /wire/core/Fieldtype.php * /wire/core/Fieldtype.php
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
*/ */
@@ -21,7 +21,7 @@ class FieldtypePassword extends Fieldtype {
'version' => 101, 'version' => 101,
'summary' => 'Field that stores a hashed and salted password', 'summary' => 'Field that stores a hashed and salted password',
'permanent' => true, 'permanent' => true,
); );
} }
/** /**
@@ -29,7 +29,7 @@ class FieldtypePassword extends Fieldtype {
* *
*/ */
public function init() { public function init() {
return parent::init(); parent::init();
} }
/** /**
@@ -120,7 +120,7 @@ class FieldtypePassword extends Fieldtype {
* @param Page $page * @param Page $page
* @param Field $field * @param Field $field
* @param string|int|array|object $value * @param string|int|array|object $value
* @return string|int * @return array|string|int
* *
*/ */
public function ___sleepValue(Page $page, Field $field, $value) { public function ___sleepValue(Page $page, Field $field, $value) {
@@ -130,7 +130,7 @@ class FieldtypePassword extends Fieldtype {
$sleepValue = array( $sleepValue = array(
'salt' => $value->salt, 'salt' => $value->salt,
'data' => $value->hash, 'data' => $value->hash,
); );
// salt not needed for blowfish since it is prepended to the hash already // salt not needed for blowfish since it is prepended to the hash already
// if($value->isBlowfish()) $sleepValue['salt'] = ''; // if($value->isBlowfish()) $sleepValue['salt'] = '';
@@ -150,7 +150,7 @@ class FieldtypePassword extends Fieldtype {
$schema = parent::getDatabaseSchema($field); $schema = parent::getDatabaseSchema($field);
$schema['data'] = 'char(40) NOT NULL'; $schema['data'] = 'char(40) NOT NULL';
$schema['salt'] = 'char(32) NOT NULL'; $schema['salt'] = 'char(32) NOT NULL';
$engine = $this->wire('config')->dbEngine; $engine = $this->wire()->config->dbEngine;
$schema['xtra']['append'] = "ENGINE=$engine DEFAULT CHARSET=ascii"; $schema['xtra']['append'] = "ENGINE=$engine DEFAULT CHARSET=ascii";
return $schema; return $schema;
} }
@@ -168,4 +168,3 @@ class FieldtypePassword extends Fieldtype {
return $inputfields; return $inputfields;
} }
} }

View File

@@ -69,7 +69,7 @@
* For documentation about the fields used in this class, please see: * For documentation about the fields used in this class, please see:
* /wire/core/Fieldtype.php * /wire/core/Fieldtype.php
* *
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* *
@@ -117,7 +117,7 @@ class FieldtypeToggle extends Fieldtype {
* *
* @param Page $page * @param Page $page
* @param Field $field * @param Field $field
* @return mixed * @return string
* *
*/ */
public function getDefaultValue(Page $page, Field $field) { public function getDefaultValue(Page $page, Field $field) {
@@ -142,7 +142,6 @@ class FieldtypeToggle extends Fieldtype {
* *
*/ */
public function isEmptyValue(Field $field, $value) { public function isEmptyValue(Field $field, $value) {
if($field) {}
// 0 is allowed because it represents "no/off" selection // 0 is allowed because it represents "no/off" selection
if($value === 0 || $value === "0") return false; if($value === 0 || $value === "0") return false;
if($value === 'unknown' || "$value" === "-1") return true; if($value === 'unknown' || "$value" === "-1") return true;
@@ -180,7 +179,7 @@ class FieldtypeToggle extends Fieldtype {
* @param Page $page * @param Page $page
* @param Field $field * @param Field $field
* @param int|object|WireArray|string $value * @param int|object|WireArray|string $value
* @return int|object|WireArray|string * @return string
* *
*/ */
public function sanitizeValue(Page $page, Field $field, $value) { public function sanitizeValue(Page $page, Field $field, $value) {
@@ -202,8 +201,7 @@ class FieldtypeToggle extends Fieldtype {
* @param Field $field * @param Field $field
* @param int|string|null $value * @param int|string|null $value
* @param string $property * @param string $property
* * @return string
* @return MarkupFieldtype|string
* *
*/ */
public function ___markupValue(Page $page, Field $field, $value = null, $property = '') { public function ___markupValue(Page $page, Field $field, $value = null, $property = '') {
@@ -224,7 +222,7 @@ class FieldtypeToggle extends Fieldtype {
*/ */
public function getInputfield(Page $page, Field $field) { public function getInputfield(Page $page, Field $field) {
/** @var InputfieldToggle $f */ /** @var InputfieldToggle $f */
$f = $this->wire('modules')->get('InputfieldToggle'); $f = $this->wire()->modules->get('InputfieldToggle');
return $f; return $f;
} }
@@ -243,13 +241,12 @@ class FieldtypeToggle extends Fieldtype {
} }
/** /**
* @param DatabaseQuerySelect $query * @param DatabaseQuerySelect|PageFinderDatabaseQuerySelect $query
* @param string $table * @param string $table
* @param string $subfield * @param string $subfield
* @param string $operator * @param string $operator
* @param mixed $value * @param mixed $value
* * @return DatabaseQuerySelect|PageFinderDatabaseQuerySelect
* @return DatabaseQuery|DatabaseQuerySelect
* @throws WireException * @throws WireException
* *
*/ */
@@ -323,9 +320,8 @@ class FieldtypeToggle extends Fieldtype {
* *
*/ */
public function ___getCompatibleFieldtypes(Field $field) { public function ___getCompatibleFieldtypes(Field $field) {
if($field) {}
$fieldtypes = $this->wire(new Fieldtypes()); $fieldtypes = $this->wire(new Fieldtypes());
foreach($this->wire('fieldtypes') as $fieldtype) { foreach($this->wire()->fieldtypes as $fieldtype) {
if($fieldtype instanceof FieldtypeToggle || $fieldtype instanceof FieldtypeCheckbox) { if($fieldtype instanceof FieldtypeToggle || $fieldtype instanceof FieldtypeCheckbox) {
$fieldtypes->add($fieldtype); $fieldtypes->add($fieldtype);
} }
@@ -339,12 +335,11 @@ class FieldtypeToggle extends Fieldtype {
* @param Page $page * @param Page $page
* @param Field $field * @param Field $field
* @param string|int|float|array|object $value * @param string|int|float|array|object $value
* @return string|int|float|array * @return string
* @see Fieldtype::wakeupValue() * @see Fieldtype::wakeupValue()
* *
*/ */
public function ___sleepValue(Page $page, Field $field, $value) { public function ___sleepValue(Page $page, Field $field, $value) {
if($page && $field) {}
return $this->_sanitizeValue($value); return $this->_sanitizeValue($value);
} }
@@ -371,11 +366,11 @@ class FieldtypeToggle extends Fieldtype {
} else if($formatType === self::formatString || $formatType === self::formatEntities) { } else if($formatType === self::formatString || $formatType === self::formatEntities) {
/** @var InputfieldToggle $f */ /** @var InputfieldToggle $f */
$f = $field->getInputfield($page, $field); $f = $field->getInputfield($page, $field);
if($f && $f instanceof InputfieldToggle) { if($f instanceof InputfieldToggle) {
$value = $f->getValueLabel($value); $value = $f->getValueLabel($value);
if($formatType == self::formatEntities) $value = $f->formatLabel($value, false); if($formatType == self::formatEntities) $value = $f->formatLabel($value, false);
} else if($formatType == self::formatEntities) { } else if($formatType == self::formatEntities) {
$value = $this->wire('sanitizer')->entities1($value); $value = $this->wire()->sanitizer->entities1($value);
} }
} }
@@ -393,7 +388,7 @@ class FieldtypeToggle extends Fieldtype {
$inputfields = parent::___getConfigInputfields($field); $inputfields = parent::___getConfigInputfields($field);
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $this->modules->get('InputfieldRadios'); $f = $this->wire()->modules->get('InputfieldRadios');
$f->attr('name', 'formatType'); $f->attr('name', 'formatType');
$f->attr('value', (int) $field->get('formatType')); $f->attr('value', (int) $field->get('formatType'));
$f->label = $this->_('What do you want the formatted value of your toggle field to be?'); $f->label = $this->_('What do you want the formatted value of your toggle field to be?');
@@ -418,4 +413,3 @@ class FieldtypeToggle extends Fieldtype {
} }
} }

View File

@@ -25,10 +25,6 @@ class FieldtypeURL extends FieldtypeText {
); );
} }
public function init() {
parent::init();
}
/** /**
* Sanitize value for storage * Sanitize value for storage
* *
@@ -73,7 +69,7 @@ class FieldtypeURL extends FieldtypeText {
*/ */
public function ___formatValue(Page $page, Field $field, $value) { public function ___formatValue(Page $page, Field $field, $value) {
if($field->get('addRoot') && !$field->get('noRelative') && substr($value, 0, 1) == '/') { if($field->get('addRoot') && !$field->get('noRelative') && substr($value, 0, 1) == '/') {
$root = rtrim($this->config->urls->root, '/'); $root = rtrim($this->wire()->config->urls->root, '/');
$value = $root . $value; $value = $root . $value;
} }
$value = parent::___formatValue($page, $field, $value); $value = parent::___formatValue($page, $field, $value);
@@ -159,4 +155,3 @@ class FieldtypeURL extends FieldtypeText {
// @todo add markupValue() // @todo add markupValue()
} }

View File

@@ -3,7 +3,7 @@
/** /**
* An Inputfield for handling a single checkbox * An Inputfield for handling a single checkbox
* *
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* Note: if you want a checkbox already checked, you need to add a setAttribute('checked', 'checked'); * Note: if you want a checkbox already checked, you need to add a setAttribute('checked', 'checked');
@@ -324,6 +324,7 @@ class InputfieldCheckbox extends Inputfield {
// if working with fieldtype, no additional settings are applicable // if working with fieldtype, no additional settings are applicable
if($this->hasFieldtype) return $inputfields; if($this->hasFieldtype) return $inputfields;
/** @var InputfieldText $f */
$f = $this->wire()->modules->get('InputfieldText'); $f = $this->wire()->modules->get('InputfieldText');
$f->attr('name', 'checkedValue'); $f->attr('name', 'checkedValue');
$f->attr('value', $this->checkedValue); $f->attr('value', $this->checkedValue);
@@ -333,6 +334,7 @@ class InputfieldCheckbox extends Inputfield {
$f->required = true; $f->required = true;
$inputfields->add($f); $inputfields->add($f);
/** @var InputfieldText $f */
$f = $this->wire()->modules->get('InputfieldText'); $f = $this->wire()->modules->get('InputfieldText');
$f->attr('name', 'uncheckedValue'); $f->attr('name', 'uncheckedValue');
$f->attr('value', "$this->uncheckedValue"); $f->attr('value', "$this->uncheckedValue");

View File

@@ -8,7 +8,7 @@
* For documentation about the fields used in this class, please see: * For documentation about the fields used in this class, please see:
* /wire/core/Fieldtype.php * /wire/core/Fieldtype.php
* *
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* ~~~~~~ * ~~~~~~
@@ -147,7 +147,7 @@ class InputfieldDatetime extends Inputfield {
$this->set('subMinute', 0); $this->set('subMinute', 0);
$this->set('requiredAttr', 0); $this->set('requiredAttr', 0);
foreach($this->getInputTypes() as $name => $type) { foreach($this->getInputTypes() as $type) {
$this->setArray($type->getDefaultSettings()); $this->setArray($type->getDefaultSettings());
} }
@@ -297,7 +297,7 @@ class InputfieldDatetime extends Inputfield {
$format .= self::defaultTimeInputFormat; $format .= self::defaultTimeInputFormat;
} }
return $this->wire('datetime')->formatDate($value, trim($format)); return $this->wire()->datetime->formatDate($value, trim($format));
} }
/** /**
@@ -364,7 +364,7 @@ class InputfieldDatetime extends Inputfield {
$inputfields = parent::___getConfigInputfields(); $inputfields = parent::___getConfigInputfields();
$inputTypes = $this->getInputTypes(); $inputTypes = $this->getInputTypes();
$modules = $this->wire('modules'); /** @var Modules $modules */ $modules = $this->wire()->modules;
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $modules->get('InputfieldRadios'); $f = $modules->get('InputfieldRadios');
@@ -383,7 +383,7 @@ class InputfieldDatetime extends Inputfield {
$inputfields->add($f); $inputfields->add($f);
foreach($inputTypes as $inputTypeName => $inputType) { foreach($inputTypes as $inputTypeName => $inputType) {
/** @var InputfieldFieldset $inputfields */ /** @var InputfieldFieldset $fieldset */
$fieldset = $modules->get('InputfieldFieldset'); $fieldset = $modules->get('InputfieldFieldset');
$fieldset->attr('name', '_' . $inputTypeName . 'Options'); $fieldset->attr('name', '_' . $inputTypeName . 'Options');
$fieldset->label = $inputType->getTypeLabel(); $fieldset->label = $inputType->getTypeLabel();
@@ -393,7 +393,7 @@ class InputfieldDatetime extends Inputfield {
} }
/** @var InputfieldCheckbox $f */ /** @var InputfieldCheckbox $f */
$f = $this->modules->get('InputfieldCheckbox'); $f = $modules->get('InputfieldCheckbox');
$f->setAttribute('name', 'defaultToday'); $f->setAttribute('name', 'defaultToday');
$f->attr('value', 1); $f->attr('value', 1);
if($this->defaultToday) $f->attr('checked', 'checked'); if($this->defaultToday) $f->attr('checked', 'checked');

View File

@@ -36,6 +36,8 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
*/ */
public function getDefaultSettings() { public function getDefaultSettings() {
$languages = $this->wire()->languages;
$a = array( $a = array(
'datepicker' => self::datepickerNo, 'datepicker' => self::datepickerNo,
'dateInputFormat' => InputfieldDatetime::defaultDateInputFormat, 'dateInputFormat' => InputfieldDatetime::defaultDateInputFormat,
@@ -43,9 +45,9 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
'timeInputSelect' => 0, 'timeInputSelect' => 0,
'yearRange' => '', 'yearRange' => '',
); );
if($this->languages) { if($languages) {
foreach($this->languages as $language) { foreach($languages as $language) {
/** @var Language $language */ /** @var Language $language */
// account for alternate formats in other languages // account for alternate formats in other languages
if($language->isDefault()) continue; if($language->isDefault()) continue;
@@ -67,8 +69,8 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
*/ */
public function renderReady() { public function renderReady() {
/** @var Config $config */ $config = $this->wire()->config;
$config = $this->wire('config'); $modules = $this->wire()->modules;
// this method only needs to run if datepicker is in use // this method only needs to run if datepicker is in use
$datepicker = (int) $this->getSetting('datepicker'); $datepicker = (int) $this->getSetting('datepicker');
@@ -78,10 +80,10 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
if($dateFormat) {} // not used here if($dateFormat) {} // not used here
$useTime = false; $useTime = false;
$language = $this->wire('languages') ? $this->wire('user')->language : null; $language = $this->wire()->languages ? $this->wire()->user->language : null;
$this->wire('modules')->get('JqueryCore'); // Jquery Core required before Jquery UI $modules->get('JqueryCore'); // Jquery Core required before Jquery UI
$this->wire('modules')->get('JqueryUI'); $modules->get('JqueryUI');
$this->inputfield->addClass("InputfieldDatetimeDatepicker InputfieldDatetimeDatepicker{$datepicker}"); $this->inputfield->addClass("InputfieldDatetimeDatepicker InputfieldDatetimeDatepicker{$datepicker}");
if(strlen($timeFormat) && $datepicker != self::datepickerInline) { if(strlen($timeFormat) && $datepicker != self::datepickerInline) {
@@ -128,11 +130,8 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
*/ */
public function render() { public function render() {
/** @var Sanitizer $sanitizer */ $sanitizer = $this->wire()->sanitizer;
$sanitizer = $this->wire('sanitizer'); $datetime = $this->wire()->datetime;
/** @var WireDateTime $datetime */
$datetime = $this->wire('datetime');
$datepicker = (int) $this->getSetting('datepicker'); $datepicker = (int) $this->getSetting('datepicker');
@@ -169,6 +168,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
if(strlen($timeFormatJS)) $timeFormatJS = $sanitizer->entities($timeFormatJS); if(strlen($timeFormatJS)) $timeFormatJS = $sanitizer->entities($timeFormatJS);
if(empty($value)) $value = ''; if(empty($value)) $value = '';
$yearRange = $sanitizer->entities($this->getSetting('yearRange')); $yearRange = $sanitizer->entities($this->getSetting('yearRange'));
$timeInputSelect = $this->getSetting('timeInputSelect'); $timeInputSelect = $this->getSetting('timeInputSelect');
@@ -196,7 +196,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
public function renderValue() { public function renderValue() {
$value = $this->getAttribute('value'); $value = $this->getAttribute('value');
$format = $this->getSetting('dateInputFormat') . ' ' . $this->getSetting('timeInputFormat'); $format = $this->getSetting('dateInputFormat') . ' ' . $this->getSetting('timeInputFormat');
return $format && $value ? $this->wire('datetime')->formatDate($value, trim($format)) : ''; return $format && $value ? $this->wire()->datetime->formatDate($value, trim($format)) : '';
} }
/** /**
@@ -218,8 +218,8 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
protected function getInputFormat($getArray = false) { protected function getInputFormat($getArray = false) {
$inputFormats = array(); $inputFormats = array();
$language = $this->wire('user')->language; $language = $this->wire()->user->language;
$useLanguages = $this->wire('languages') && $language && !$language->isDefault(); $useLanguages = $this->wire()->languages && $language && !$language->isDefault();
foreach(array('date', 'time') as $type) { foreach(array('date', 'time') as $type) {
$inputFormat = ''; $inputFormat = '';
@@ -248,7 +248,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
public function sanitizeValue($value) { public function sanitizeValue($value) {
// convert date string to unix timestamp // convert date string to unix timestamp
$format = $this->getInputFormat(); $format = $this->getInputFormat();
$value = $this->wire('datetime')->stringToTimestamp($value, $format); $value = $this->wire()->datetime->stringToTimestamp($value, $format);
return $value; return $value;
} }
@@ -258,14 +258,16 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
*/ */
public function getConfigInputfields(InputfieldWrapper $inputfields) { public function getConfigInputfields(InputfieldWrapper $inputfields) {
$languages = $this->wire('languages'); $languages = $this->wire()->languages;
$datetime = $this->wire('datetime'); $datetime = $this->wire()->datetime;
$modules = $this->wire()->modules;
$dateInputFormat = $this->getSetting('dateInputFormat'); $dateInputFormat = $this->getSetting('dateInputFormat');
$timeInputFormat = $this->getSetting('timeInputFormat'); $timeInputFormat = $this->getSetting('timeInputFormat');
$timeInputSelect = (int) $this->getSetting('timeInputSelect'); $timeInputSelect = (int) $this->getSetting('timeInputSelect');
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $this->modules->get('InputfieldRadios'); $f = $modules->get('InputfieldRadios');
$f->label = $this->_('Date Picker'); $f->label = $this->_('Date Picker');
$f->setAttribute('name', 'datepicker'); $f->setAttribute('name', 'datepicker');
$f->addOption(self::datepickerNo, $this->_('No date/time picker')); $f->addOption(self::datepickerNo, $this->_('No date/time picker'));
@@ -278,12 +280,12 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$inputfields->append($f); $inputfields->append($f);
/** @var InputfieldFieldset $fieldset */ /** @var InputfieldFieldset $fieldset */
$fieldset = $this->modules->get('InputfieldFieldset'); $fieldset = $modules->get('InputfieldFieldset');
$fieldset->attr('name', '_dateTimeInputFormats'); $fieldset->attr('name', '_dateTimeInputFormats');
$fieldset->label = $this->_('Date/Time Input Formats'); $fieldset->label = $this->_('Date/Time Input Formats');
/** @var InputfieldSelect $f */ /** @var InputfieldSelect $f */
$f = $this->modules->get('InputfieldSelect'); $f = $modules->get('InputfieldSelect');
$f->attr('name', '_dateInputFormat'); $f->attr('name', '_dateInputFormat');
$f->label = $this->_('Date Input Format'); $f->label = $this->_('Date Input Format');
$f->description = $this->_('Select the format to be used for user input to this field. Your selection will populate the field below this, which you may customize further if needed.'); $f->description = $this->_('Select the format to be used for user input to this field. Your selection will populate the field below this, which you may customize further if needed.');
@@ -299,7 +301,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$fieldset->add($f); $fieldset->add($f);
/** @var InputfieldSelect $f */ /** @var InputfieldSelect $f */
$f = $this->modules->get('InputfieldSelect'); $f = $modules->get('InputfieldSelect');
$f->attr('name', '_timeInputFormat'); $f->attr('name', '_timeInputFormat');
$f->label = $this->_('Time Input Format'); $f->label = $this->_('Time Input Format');
$f->addOption('', $this->_('None')); $f->addOption('', $this->_('None'));
@@ -317,7 +319,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$fieldset->add($f); $fieldset->add($f);
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $this->modules->get("InputfieldRadios"); $f = $modules->get("InputfieldRadios");
$f->attr('name', 'timeInputSelect'); $f->attr('name', 'timeInputSelect');
$f->label = $this->_('Time Input Type'); $f->label = $this->_('Time Input Type');
$f->description = $this->_('Sliders (default) let the user slide controls to choose the time, where as Select lets the user select the time from a drop-down select.'); $f->description = $this->_('Sliders (default) let the user slide controls to choose the time, where as Select lets the user select the time from a drop-down select.');
@@ -331,7 +333,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$fieldset->add($f); $fieldset->add($f);
/** @var InputfieldText $f */ /** @var InputfieldText $f */
$f = $this->modules->get("InputfieldText"); $f = $modules->get("InputfieldText");
$f->attr('name', 'dateInputFormat'); $f->attr('name', 'dateInputFormat');
$f->attr('value', $dateInputFormat ? $dateInputFormat : InputfieldDatetime::defaultDateInputFormat); $f->attr('value', $dateInputFormat ? $dateInputFormat : InputfieldDatetime::defaultDateInputFormat);
$f->attr('size', 20); $f->attr('size', 20);
@@ -346,7 +348,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$fieldset->add($f); $fieldset->add($f);
/** @var InputfieldText $f */ /** @var InputfieldText $f */
$f = $this->modules->get("InputfieldText"); $f = $modules->get("InputfieldText");
$f->attr('name', 'timeInputFormat'); $f->attr('name', 'timeInputFormat');
$f->attr('value', $timeInputFormat ? $timeInputFormat : ''); $f->attr('value', $timeInputFormat ? $timeInputFormat : '');
$f->attr('size', 20); $f->attr('size', 20);
@@ -372,8 +374,8 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$inputfields->add($fieldset); $inputfields->add($fieldset);
/** @var InputfieldText $field */ /** @var InputfieldText $f */
$f = $this->modules->get('InputfieldText'); $f = $modules->get('InputfieldText');
$f->setAttribute('name', 'placeholder'); $f->setAttribute('name', 'placeholder');
$f->label = $this->_('Placeholder Text'); $f->label = $this->_('Placeholder Text');
$f->setAttribute('value', $this->getAttribute('placeholder')); $f->setAttribute('value', $this->getAttribute('placeholder'));
@@ -382,7 +384,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$inputfields->append($f); $inputfields->append($f);
/** @var InputfieldInteger $f */ /** @var InputfieldInteger $f */
$f = $this->modules->get('InputfieldInteger'); $f = $modules->get('InputfieldInteger');
$f->setAttribute('name', 'size'); $f->setAttribute('name', 'size');
$f->label = $this->_('Size'); $f->label = $this->_('Size');
$f->attr('value', $this->getAttribute('size')); $f->attr('value', $this->getAttribute('size'));
@@ -392,7 +394,7 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
$inputfields->append($f); $inputfields->append($f);
/** @var InputfieldText $f */ /** @var InputfieldText $f */
$f = $this->modules->get("InputfieldText"); $f = $modules->get("InputfieldText");
$f->attr('name', 'yearRange'); $f->attr('name', 'yearRange');
$f->attr('value', $this->getSetting('yearRange')); $f->attr('value', $this->getSetting('yearRange'));
$f->attr('size', 10); $f->attr('size', 10);
@@ -408,4 +410,4 @@ class InputfieldDatetimeText extends InputfieldDatetimeType {
} }
} }

View File

@@ -118,7 +118,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
'ł' => 'l', 'ł' => 'l',
'ż' => 'z', 'ż' => 'z',
'ź' => 'z', 'ź' => 'z',
); );
/** /**
* Whether or not the system has LanguageSupportPageNames module installed * Whether or not the system has LanguageSupportPageNames module installed
@@ -155,13 +155,15 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
$this->description = $this->_("Any combination of letters (a-z), numbers (0-9), dashes or underscores (no spaces)."); // Field description describing what characters are allowed $this->description = $this->_("Any combination of letters (a-z), numbers (0-9), dashes or underscores (no spaces)."); // Field description describing what characters are allowed
$this->set('sanitizeMethod', 'pageName'); $this->set('sanitizeMethod', 'pageName');
} }
$this->hasLanguagePageNames = $this->wire('modules')->isInstalled('LanguageSupportPageNames'); $this->hasLanguagePageNames = $this->wire()->modules->isInstalled('LanguageSupportPageNames');
$this->removeClass('InputfieldNoBorder', 'wrapClass'); $this->removeClass('InputfieldNoBorder', 'wrapClass');
} }
public function ___render() { public function ___render() {
$config = $this->wire()->config;
$url = ''; $url = '';
$out = ''; $out = '';
$box = ''; $box = '';
@@ -181,7 +183,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
} else { } else {
$url = $this->parentPage->path; $url = $this->parentPage->path;
} }
if($this->hasLanguagePageNames && $this->parentPage->id == $this->wire('config')->rootPageID) { if($this->hasLanguagePageNames && $this->parentPage->id == $config->rootPageID) {
if($user->language->isDefault()) { if($user->language->isDefault()) {
$parentName = $this->parentPage->name; $parentName = $this->parentPage->name;
if(!trim($url, '/')) $url = ($parentName === Pages::defaultRootName ? "" : $parentName); if(!trim($url, '/')) $url = ($parentName === Pages::defaultRootName ? "" : $parentName);
@@ -221,7 +223,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
if(strlen($value) && $this->hasLanguagePageNames) { if(strlen($value) && $this->hasLanguagePageNames) {
$link = trim($url, '/') . "/$value" . ($slashUrls ? '/' : ''); $link = trim($url, '/') . "/$value" . ($slashUrls ? '/' : '');
$link = $this->wire('config')->urls->root . ltrim($link, '/'); $link = $config->urls->root . ltrim($link, '/');
$link = "<a href='$link'>"; $link = "<a href='$link'>";
} }
@@ -238,7 +240,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
if($this->languageSupportLabel) $out .= $box . "</div>"; if($this->languageSupportLabel) $out .= $box . "</div>";
// make the replacements part of the JS config // make the replacements part of the JS config
$charset = $this->wire('config')->pageNameCharset; $charset = $config->pageNameCharset;
if($charset == 'UTF8') { if($charset == 'UTF8') {
$replacements = array(':' => '-', ',' => '-'); $replacements = array(':' => '-', ',' => '-');
$whitelist = $this->config->pageNameWhitelist; $whitelist = $this->config->pageNameWhitelist;
@@ -246,7 +248,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
$replacements = empty($this->replacements) ? self::$defaultReplacements : $this->replacements; $replacements = empty($this->replacements) ? self::$defaultReplacements : $this->replacements;
$whitelist = ''; $whitelist = '';
} }
$this->config->js($this->className(), array( $config->js($this->className(), array(
'replacements' => $replacements, 'replacements' => $replacements,
'charset' => $charset, 'charset' => $charset,
'whitelist' => $whitelist 'whitelist' => $whitelist
@@ -257,14 +259,14 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
public function ___processInput(WireInputData $input) { public function ___processInput(WireInputData $input) {
if($this->attr('disabled')) return $this; if($this->attr('disabled')) return $this;
$languages = $this->wire('languages'); $languages = $this->wire()->languages;
if($this->editPage && $this->editPage->template->noLang) $languages = false; if($this->editPage && $this->editPage->template->noLang) $languages = false;
if($languages && $this->hasLanguagePageNames) { if($languages && $this->hasLanguagePageNames) {
$user = $this->wire('user'); $user = $this->wire()->user;
if(!$languages->editable($user->language)) return $this; if(!$languages->editable($user->language)) return $this;
$return = parent::___processInput($input); $return = parent::___processInput($input);
$process = $this->wire('process'); $process = $this->wire()->process;
if($process instanceof WirePageEditor && $process->getPage()->id == $this->wire('config')->rootPageID) { if($process instanceof WirePageEditor && $process->getPage()->id == $this->wire()->config->rootPageID) {
if(!strlen($this->attr('value'))) { if(!strlen($this->attr('value'))) {
$this->attr('value', Pages::defaultRootName); $this->attr('value', Pages::defaultRootName);
} }
@@ -278,7 +280,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
static public function replacementStringToArray($str) { static public function replacementStringToArray($str) {
$r = preg_split('/[\r\n]+/', $str); $r = preg_split('/[\r\n]+/', $str);
$a = array(); $a = array();
foreach($r as $key => $value) { foreach($r as $value) {
if(!strpos($value, '=')) continue; if(!strpos($value, '=')) continue;
list($k, $v) = explode('=', $value); list($k, $v) = explode('=', $value);
$a[trim($k)] = trim($v); $a[trim($k)] = trim($v);
@@ -293,14 +295,14 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
} }
public function getModuleConfigInputfields(array $data) { public function getModuleConfigInputfields(array $data) {
$modules = $this->wire()->modules;
$fields = $this->wire(new InputfieldWrapper()); $fields = $this->wire(new InputfieldWrapper());
if($this->wire('config')->pageNameCharset === 'UTF8') { if($this->wire()->config->pageNameCharset === 'UTF8') {
$this->message($this->_('Character replacements configuration is disabled because $config->pageNameCharset is UTF8.')); $this->message($this->_('Character replacements configuration is disabled because $config->pageNameCharset is UTF8.'));
return $fields; return $fields;
} }
$modules = $this->wire('modules');
$modules->addHookBefore('saveModuleConfigData', null, 'InputfieldPageName_saveModuleConfigData'); $modules->addHookBefore('saveModuleConfigData', null, 'InputfieldPageName_saveModuleConfigData');
$name = 'replacements'; $name = 'replacements';
@@ -317,6 +319,7 @@ class InputfieldPageName extends InputfieldName implements ConfigurableModule {
$data[$name] = self::replacementStringToArray($replacements); $data[$name] = self::replacementStringToArray($replacements);
} }
/** @var InputfieldTextarea $field */
$field = $modules->get("InputfieldTextarea"); $field = $modules->get("InputfieldTextarea");
$field->attr('name', $name); $field->attr('name', $name);
$field->attr('value', $replacements); $field->attr('value', $replacements);
@@ -350,4 +353,3 @@ function InputfieldPageName_saveModuleConfigData(HookEvent $event) {
$arguments[1] = $data; $arguments[1] = $data;
$event->arguments = $arguments; $event->arguments = $arguments;
} }

View File

@@ -3,7 +3,7 @@
/** /**
* An Inputfield for handling a password * An Inputfield for handling a password
* *
* ProcessWire 3.x, Copyright 2021 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @property array $requirements Array of requirements (See require* constants) * @property array $requirements Array of requirements (See require* constants)
@@ -27,7 +27,7 @@ class InputfieldPassword extends InputfieldText {
'summary' => __("Password input with confirmation field that doesn't ever echo the input back.", __FILE__), // Module Summary 'summary' => __("Password input with confirmation field that doesn't ever echo the input back.", __FILE__), // Module Summary
'version' => 102, 'version' => 102,
'permanent' => true, 'permanent' => true,
); );
} }
/** /**
@@ -106,19 +106,8 @@ class InputfieldPassword extends InputfieldText {
$this->set('requirements', array(self::requireLetter, self::requireDigit)); $this->set('requirements', array(self::requireLetter, self::requireDigit));
$this->set('complexifyFactor', 0.7); $this->set('complexifyFactor', 0.7);
$this->set('complexifyBanMode', 'loose'); $this->set('complexifyBanMode', 'loose');
$this->set('requirementsLabels', array(
self::requireLetter => $this->_('letter'),
self::requireLowerLetter => $this->_('lowercase letter'),
self::requireUpperLetter => $this->_('uppercase letter'),
self::requireDigit => $this->_('digit'),
self::requireOther => $this->_('symbol/punctuation'),
self::requireNone => $this->_('none (disable all above)'),
));
$this->set('showPass', false); // allow password to be rendered in renderValue and/or re-populated in form? $this->set('showPass', false); // allow password to be rendered in renderValue and/or re-populated in form?
$this->set('unmask', false); $this->set('unmask', false);
$this->set('oldPassLabel', $this->_('Current password'));
$this->set('newPassLabel', $this->_('New password'));
$this->set('confirmLabel', $this->_('Confirm'));
} }
/** /**
@@ -127,8 +116,20 @@ class InputfieldPassword extends InputfieldText {
*/ */
public function init() { public function init() {
parent::init(); parent::init();
$this->set('defaultLabel', $this->_('Set Password')); $defaultLabel = $this->_('Set Password');
$this->label = $this->defaultLabel; $this->set('defaultLabel', $defaultLabel);
$this->set('requirementsLabels', array(
self::requireLetter => $this->_('letter'),
self::requireLowerLetter => $this->_('lowercase letter'),
self::requireUpperLetter => $this->_('uppercase letter'),
self::requireDigit => $this->_('digit'),
self::requireOther => $this->_('symbol/punctuation'),
self::requireNone => $this->_('none (disable all above)'),
));
$this->set('oldPassLabel', $this->_('Current password'));
$this->set('newPassLabel', $this->_('New password'));
$this->set('confirmLabel', $this->_('Confirm'));
$this->label = $defaultLabel;
} }
/** /**
@@ -153,13 +154,14 @@ class InputfieldPassword extends InputfieldText {
*/ */
public function renderReady(Inputfield $parent = null, $renderValueMode = false) { public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
if($this->label == 'Set Password') $this->label = $this->defaultLabel; if($this->label == 'Set Password') $this->label = $this->defaultLabel;
$config = $this->wire('config'); $config = $this->wire()->config;
$url = $config->urls->InputfieldPassword . 'complexify/'; $url = $config->urls('InputfieldPassword') . 'complexify/';
$config->scripts->add($url . 'jquery.complexify.min.js'); $config->scripts->add($url . 'jquery.complexify.min.js');
$config->scripts->add($url . 'jquery.complexify.banlist.js'); $config->scripts->add($url . 'jquery.complexify.banlist.js');
$this->wire('modules')->get('JqueryCore')->use('xregexp'); $jQueryCore = $this->wire()->modules->get('JqueryCore'); /** @var JqueryCore $jQueryCore */
$page = $this->wire('page'); $jQueryCore->use('xregexp');
if(($page && $page->template == 'admin') || $this->wire('user')->isLoggedin()) { $page = $this->wire()->page;
if(($page && $page->template->name == 'admin') || $this->wire()->user->isLoggedin()) {
$this->attr('autocomplete', 'new-password'); // ProcessProfile and ProcessUser $this->attr('autocomplete', 'new-password'); // ProcessProfile and ProcessUser
} }
return parent::renderReady($parent, $renderValueMode); return parent::renderReady($parent, $renderValueMode);
@@ -173,8 +175,7 @@ class InputfieldPassword extends InputfieldText {
*/ */
public function ___render() { public function ___render() {
/** @var Sanitizer $sanitizer */ $sanitizer = $this->wire()->sanitizer;
$sanitizer = $this->wire('sanitizer');
$minlength = (int) $this->attr('minlength'); $minlength = (int) $this->attr('minlength');
$requirements = array(); $requirements = array();
@@ -207,13 +208,13 @@ class InputfieldPassword extends InputfieldText {
if(!$this->getSetting('showPass')) { if(!$this->getSetting('showPass')) {
$this->attr('value', ''); $this->attr('value', '');
} else { } else {
$confirmValue = $this->wire('sanitizer')->entities($value); $confirmValue = $sanitizer->entities($value);
} }
$this->attr('data-banMode', $this->complexifyBanMode ? $this->complexifyBanMode : 'loose'); $this->attr('data-banMode', $this->complexifyBanMode ? $this->complexifyBanMode : 'loose');
$this->attr('data-factor', (float) $this->complexifyFactor >= 0 ? str_replace(',', '.', "$this->complexifyFactor") : 0); $this->attr('data-factor', (float) $this->complexifyFactor >= 0 ? str_replace(',', '.', "$this->complexifyFactor") : 0);
$inputClass = $this->wire('sanitizer')->entities($this->attr('class')); $inputClass = $sanitizer->entities($this->attr('class'));
$this->addClass('InputfieldPasswordComplexify'); $this->addClass('InputfieldPasswordComplexify');
$failIcon = "<i class='fa fa-fw fa-frown-o'></i>"; $failIcon = "<i class='fa fa-fw fa-frown-o'></i>";
@@ -227,7 +228,7 @@ class InputfieldPassword extends InputfieldText {
$size = $this->attr('size'); $size = $this->attr('size');
$out = ''; $out = '';
if((int) $this->requireOld > 0 && $this->wire('user')->isLoggedin()) { if((int) $this->requireOld > 0 && $this->wire()->user->isLoggedin()) {
$out .= $out .=
"<p class='InputfieldPasswordRow'>" . "<p class='InputfieldPasswordRow'>" .
"<label for='_old_$name'>$oldPassLabel</label>" . "<label for='_old_$name'>$oldPassLabel</label>" .
@@ -305,7 +306,7 @@ class InputfieldPassword extends InputfieldText {
if(!$this->getSetting('showPass')) { if(!$this->getSetting('showPass')) {
$value = strlen($this->attr('value')) ? '******' : ''; $value = strlen($this->attr('value')) ? '******' : '';
} else { } else {
$value = $this->wire('sanitizer')->entities($this->attr('value')); $value = $this->wire()->sanitizer->entities($this->attr('value'));
} }
$value = strlen($value) ? "<p>$value</p>" : ""; $value = strlen($value) ? "<p>$value</p>" : "";
return $value; return $value;
@@ -322,8 +323,7 @@ class InputfieldPassword extends InputfieldText {
parent::___processInput($input); parent::___processInput($input);
/** @var User $user */ $user = $this->wire()->user;
$user = $this->wire('user');
$key = $this->attr('name'); $key = $this->attr('name');
$value = $this->attr('value'); $value = $this->attr('value');
if($value) {} if($value) {}
@@ -346,7 +346,7 @@ class InputfieldPassword extends InputfieldText {
if(!strlen($oldPass)) { if(!strlen($oldPass)) {
$this->error($this->_('Old password is required in order to enter a new one.')); $this->error($this->_('Old password is required in order to enter a new one.'));
$allowInput = false; $allowInput = false;
} else if(!$this->wire('user')->pass->matches($oldPass)) { } else if(!$user->pass->matches($oldPass)) {
$this->error($this->_('The old password you entered is not correct.')); $this->error($this->_('The old password you entered is not correct.'));
$allowInput = false; $allowInput = false;
} }
@@ -446,7 +446,8 @@ class InputfieldPassword extends InputfieldText {
* *
*/ */
public function ___getConfigInputfields() { public function ___getConfigInputfields() {
$modules = $this->wire()->modules;
$inputfields = parent::___getConfigInputfields(); $inputfields = parent::___getConfigInputfields();
$skips = array( $skips = array(
'collapsed', 'collapsed',
@@ -467,7 +468,7 @@ class InputfieldPassword extends InputfieldText {
} }
/** @var InputfieldCheckboxes $f */ /** @var InputfieldCheckboxes $f */
$f = $this->wire('modules')->get('InputfieldCheckboxes'); $f = $modules->get('InputfieldCheckboxes');
$f->attr('name', 'requirements'); $f->attr('name', 'requirements');
$f->label = $this->_('Password requirements'); $f->label = $this->_('Password requirements');
foreach($this->getSetting('requirementsLabels') as $value => $label) { foreach($this->getSetting('requirementsLabels') as $value => $label) {
@@ -480,7 +481,7 @@ class InputfieldPassword extends InputfieldText {
$inputfields->add($f); $inputfields->add($f);
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $this->wire('modules')->get('InputfieldRadios'); $f = $modules->get('InputfieldRadios');
$f->attr('name', 'complexifyBanMode'); $f->attr('name', 'complexifyBanMode');
$f->label = $this->_('Word ban mode'); $f->label = $this->_('Word ban mode');
$f->description = $this->_('If you choose the strict mode, many passwords containing words will not be accepted.'); $f->description = $this->_('If you choose the strict mode, many passwords containing words will not be accepted.');
@@ -491,7 +492,7 @@ class InputfieldPassword extends InputfieldText {
$inputfields->add($f); $inputfields->add($f);
/** @var InputfieldFloat $f */ /** @var InputfieldFloat $f */
$f = $this->wire('modules')->get('InputfieldFloat'); $f = $modules->get('InputfieldFloat');
$f->attr('name', 'complexifyFactor'); $f->attr('name', 'complexifyFactor');
$f->label = $this->_('Complexify factor'); $f->label = $this->_('Complexify factor');
$f->description = $this->_('Lower numbers allow weaker passwords, higher numbers require stronger passwords.'); $f->description = $this->_('Lower numbers allow weaker passwords, higher numbers require stronger passwords.');
@@ -502,7 +503,7 @@ class InputfieldPassword extends InputfieldText {
$inputfields->add($f); $inputfields->add($f);
/** @var InputfieldInteger $f */ /** @var InputfieldInteger $f */
$f = $this->wire('modules')->get('InputfieldInteger'); $f = $modules->get('InputfieldInteger');
$f->attr('name', 'minlength'); $f->attr('name', 'minlength');
$f->label = $this->_('Minimum password length'); $f->label = $this->_('Minimum password length');
$f->attr('value', $this->attr('minlength')); $f->attr('value', $this->attr('minlength'));
@@ -512,7 +513,7 @@ class InputfieldPassword extends InputfieldText {
if(!$this->getSetting('hasFieldtype')) { if(!$this->getSetting('hasFieldtype')) {
/** @var InputfieldCheckbox $f */ /** @var InputfieldCheckbox $f */
$f = $this->wire('modules')->get('InputfieldCheckbox'); $f = $modules->get('InputfieldCheckbox');
$f->attr('name', 'showPass'); $f->attr('name', 'showPass');
$f->label = $this->_('Allow existing passwords to be shown and/or rendered in form?'); $f->label = $this->_('Allow existing passwords to be shown and/or rendered in form?');
if($this->getSetting("showPass")) $f->attr('checked', 'checked'); if($this->getSetting("showPass")) $f->attr('checked', 'checked');
@@ -520,7 +521,7 @@ class InputfieldPassword extends InputfieldText {
} }
/** @var InputfieldRadios $f */ /** @var InputfieldRadios $f */
$f = $this->wire('modules')->get('InputfieldRadios'); $f = $modules->get('InputfieldRadios');
$f->attr('name', 'requireOld'); $f->attr('name', 'requireOld');
$f->label = $this->_('Require old password before allowing changes?'); $f->label = $this->_('Require old password before allowing changes?');
$f->description = $this->_('Applies to usages where this field appears to already logged-in users only.'); $f->description = $this->_('Applies to usages where this field appears to already logged-in users only.');
@@ -530,8 +531,9 @@ class InputfieldPassword extends InputfieldText {
$f->optionColumns = 1; $f->optionColumns = 1;
$f->attr('value', (int) $this->requireOld); $f->attr('value', (int) $this->requireOld);
$inputfields->add($f); $inputfields->add($f);
$f = $this->wire()->modules->get('InputfieldRadios'); /** @var InputfieldRadios $f */
$f = $modules->get('InputfieldRadios');
$f->attr('name', 'unmask'); $f->attr('name', 'unmask');
$f->label = $this->_('Allow user to show/unmask password during changes?'); $f->label = $this->_('Allow user to show/unmask password during changes?');
$f->description = $this->_('Provides a show/hide password control so users can see what they type when in an appropriate environment.'); $f->description = $this->_('Provides a show/hide password control so users can see what they type when in an appropriate environment.');

View File

@@ -3,7 +3,7 @@
/** /**
* An Inputfield for handling single line "text" form inputs * An Inputfield for handling single line "text" form inputs
* *
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @property string $type Input type (typically "text") * @property string $type Input type (typically "text")
@@ -76,7 +76,7 @@ class InputfieldText extends Inputfield {
/** /**
* Get the default maxlength attribute value * Get the default maxlength attribute value
* *
* @return mixed * @return int
* *
*/ */
public function getDefaultMaxlength() { public function getDefaultMaxlength() {
@@ -107,7 +107,7 @@ class InputfieldText extends Inputfield {
'min' => $this->_('(at least %d required)'), 'min' => $this->_('(at least %d required)'),
'max' => $this->_('(%d max)'), 'max' => $this->_('(%d max)'),
); );
$config->scripts->add($config->urls->InputfieldText . 'InputfieldTextLength.js'); $config->scripts->add($config->urls('InputfieldText') . 'InputfieldTextLength.js');
$config->js('InputfieldTextLength', $labels); $config->js('InputfieldTextLength', $labels);
} }
} }

View File

@@ -5,7 +5,7 @@ require_once(dirname(__FILE__) . '/FieldtypeLanguageInterface.php');
/** /**
* Multi-language capable text field * Multi-language capable text field
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* *
@@ -20,7 +20,7 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
'summary' => 'Field that stores a single line of text in multiple languages', 'summary' => 'Field that stores a single line of text in multiple languages',
'permanent' => false, 'permanent' => false,
'requires' => array('LanguageSupportFields'), 'requires' => array('LanguageSupportFields'),
); );
} }
/** /**
@@ -34,7 +34,7 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
*/ */
public function sanitizeValue(Page $page, Field $field, $value) { public function sanitizeValue(Page $page, Field $field, $value) {
if(is_object($value) && $value instanceof LanguagesPageFieldValue) { if($value instanceof LanguagesPageFieldValue) {
// great, already what we wanted // great, already what we wanted
return $value; return $value;
} }
@@ -78,8 +78,9 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
public function getDatabaseSchema(Field $field) { public function getDatabaseSchema(Field $field) {
$schema = parent::getDatabaseSchema($field); $schema = parent::getDatabaseSchema($field);
$languageSupport = $this->wire('modules')->get('LanguageSupport'); /** @var LanguageSupport $languageSupport */
$maxIndex = (int) $this->wire('database')->getMaxIndexLength(); $languageSupport = $this->wire()->modules->get('LanguageSupport');
$maxIndex = (int) $this->wire()->database->getMaxIndexLength();
// note that we use otherLanguagePageIDs rather than wire('languages') because // note that we use otherLanguagePageIDs rather than wire('languages') because
// it's possible that this method may be called before the languages are known // it's possible that this method may be called before the languages are known
@@ -113,10 +114,11 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
* @param Field $field * @param Field $field
* @param string|int|float|array|object|null $value * @param string|int|float|array|object|null $value
* @param array $options Optional settings to shape the exported value, if needed. * @param array $options Optional settings to shape the exported value, if needed.
* @return string|float|int|array * @return array
* *
*/ */
public function ___exportValue(Page $page, Field $field, $value, array $options = array()) { public function ___exportValue(Page $page, Field $field, $value, array $options = array()) {
$languages = $this->wire()->languages;
if(isset($options['sleepValue'])) { if(isset($options['sleepValue'])) {
// allow a sleepValue option, for use by other language Fieldtypes that delegate // allow a sleepValue option, for use by other language Fieldtypes that delegate
// their exportValue to this one, like FieldtypeTextareaLanguage // their exportValue to this one, like FieldtypeTextareaLanguage
@@ -130,7 +132,7 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
$exportValue['default'] = $v; $exportValue['default'] = $v;
} else if(strpos($k, 'data') === 0) { } else if(strpos($k, 'data') === 0) {
$languageID = substr($k, 4); $languageID = substr($k, 4);
$language = $this->wire('languages')->get((int) $languageID); $language = $languages->get((int) $languageID);
$exportValue[$language->name] = $v; $exportValue[$language->name] = $v;
} else { } else {
$exportValue[$k] = $v; $exportValue[$k] = $v;
@@ -149,8 +151,7 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
if(!is_array($value)) { if(!is_array($value)) {
throw new WireException("Array value expected for multi-language importValue"); throw new WireException("Array value expected for multi-language importValue");
} }
/** @var Languages $languages */ $languages = $this->wire()->languages;
$languages = $this->wire('languages');
/** @var LanguagesPageFieldValue $importValue */ /** @var LanguagesPageFieldValue $importValue */
$importValue = $page->get($field->name); $importValue = $page->get($field->name);
foreach($value as $languageName => $languageValue) { foreach($value as $languageName => $languageValue) {
@@ -162,4 +163,3 @@ class FieldtypeTextLanguage extends FieldtypeText implements FieldtypeLanguageIn
} }
} }

View File

@@ -3,7 +3,7 @@
/** /**
* A type of Page that represents a single Language in ProcessWire * A type of Page that represents a single Language in ProcessWire
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* @property LanguageTranslator $translator Get instance of LanguageTranslator for this language * @property LanguageTranslator $translator Get instance of LanguageTranslator for this language
@@ -68,7 +68,7 @@ class Language extends Page {
* *
*/ */
public function translator() { public function translator() {
return $this->wire('languages')->translator($this); return $this->wire()->languages->translator($this);
} }
/** /**
@@ -98,7 +98,7 @@ class Language extends Page {
* *
*/ */
public function isCurrent() { public function isCurrent() {
return $this->id == $this->wire('user')->language->id; return $this->id == $this->wire()->user->language->id;
} }
/** /**
@@ -106,11 +106,11 @@ class Language extends Page {
* *
* #pw-internal * #pw-internal
* *
* @return Pages|PagesType * @return Languages
* *
*/ */
public function getPagesManager() { public function getPagesManager() {
return $this->wire('languages'); return $this->wire()->languages;
} }
/** /**
@@ -124,7 +124,7 @@ class Language extends Page {
* *
*/ */
public function getLocale($category = LC_ALL) { public function getLocale($category = LC_ALL) {
return $this->wire('languages')->getLocale($category, $this); return $this->wire()->languages->getLocale($category, $this);
} }
/** /**
@@ -139,7 +139,6 @@ class Language extends Page {
* *
*/ */
public function setLocale($category = LC_ALL) { public function setLocale($category = LC_ALL) {
return $this->wire('languages')->setLocale($category, $this); return $this->wire()->languages->setLocale($category, $this);
} }
} }

View File

@@ -7,7 +7,7 @@
* *
* Return the results by calling $parser->getUntranslated() and $parser->getComments(); * Return the results by calling $parser->getUntranslated() and $parser->getComments();
* *
* ProcessWire 3.x, Copyright 2020 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* *
@@ -61,6 +61,7 @@ class LanguageParser extends Wire {
* *
*/ */
public function __construct(LanguageTranslator $translator, $file) { public function __construct(LanguageTranslator $translator, $file) {
parent::__construct();
$this->translator = $translator; $this->translator = $translator;
$this->textdomain = $this->translator->filenameToTextdomain($file); $this->textdomain = $this->translator->filenameToTextdomain($file);
$this->translator->loadTextdomain($this->textdomain); $this->translator->loadTextdomain($this->textdomain);
@@ -322,7 +323,7 @@ class LanguageParser extends Wire {
$this->numFound++; $this->numFound++;
// check if there are comments in the $tail and record them if so // check if there are comments in the $tail and record them if so
if(($pos = strpos($tail, '//')) !== false) { if(strpos($tail, '//') !== false) {
if(preg_match('![^:"\']//(.+)$!', $tail, $matches)) { if(preg_match('![^:"\']//(.+)$!', $tail, $matches)) {
$comments = $matches[1]; $comments = $matches[1];
} }

View File

@@ -3,7 +3,7 @@
/** /**
* Serves as a multi-language value placeholder for field values that contain a value in more than one language. * Serves as a multi-language value placeholder for field values that contain a value in more than one language.
* *
* ProcessWire 3.x, Copyright 2022 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
*/ */
@@ -117,10 +117,11 @@ class LanguagesPageFieldValue extends Wire implements LanguagesValueInterface, \
if(strpos($testKey, 'data') !== 0) { if(strpos($testKey, 'data') !== 0) {
// array does not use "data123" indexes, so work with language ID or language name indexes // array does not use "data123" indexes, so work with language ID or language name indexes
// and convert to "data123" indexes // and convert to "data123" indexes
$languages = $this->wire()->languages;
$_values = array(); $_values = array();
foreach($values as $key => $value) { foreach($values as $key => $value) {
if(ctype_digit("$key")) $key = (int) $key; if(ctype_digit("$key")) $key = (int) $key;
$language = $this->wire()->languages->get($key); $language = $languages->get($key);
if($language && $language->id) { if($language && $language->id) {
$dataKey = $language->isDefault() ? "data" : "data$language->id"; $dataKey = $language->isDefault() ? "data" : "data$language->id";
$_values[$dataKey] = $value; $_values[$dataKey] = $value;
@@ -419,5 +420,3 @@ class LanguagesPageFieldValue extends Wire implements LanguagesValueInterface, \
return $this->defaultLanguagePageID; return $this->defaultLanguagePageID;
} }
} }

View File

@@ -64,19 +64,28 @@ class ProcessLanguage extends ProcessPageType {
$this->set('showFields', $showFields); $this->set('showFields', $showFields);
$this->set('jsonListLabel', 'title|name'); $this->set('jsonListLabel', 'title|name');
require_once(dirname(__FILE__) . '/LanguageParser.php'); require_once(dirname(__FILE__) . '/LanguageParser.php');
}
/**
* Wired to ProcessWire instance
*
*/
public function wired() {
parent::wired();
$fields = $this->wire()->fields;
// make sure our files fields have CSV support // make sure our files fields have CSV support
foreach(array('language_files', 'language_files_site') as $fieldName) { foreach(array('language_files', 'language_files_site') as $fieldName) {
$field = $this->wire('fields')->get($fieldName); $field = $fields->get($fieldName);
if(!$field) continue; if(!$field) continue;
$extensions = $field->get('extensions'); $extensions = $field->get('extensions');
if(strpos($extensions, 'csv') === false) { if(strpos($extensions, 'csv') === false) {
$field->set('extensions', "$extensions csv"); $field->set('extensions', "$extensions csv");
$field->save(); $field->save();
$this->message("Added CSV support to field $fieldName", Notice::debug); $this->message("Added CSV support to field $fieldName", Notice::debug);
} }
} }
$this->csvImportLabel = $this->_('CSV Import:') . ' '; $this->csvImportLabel = $this->_('CSV Import:') . ' ';
} }
@@ -85,7 +94,7 @@ class ProcessLanguage extends ProcessPageType {
* *
*/ */
public function init() { public function init() {
$this->addHookBefore('InputfieldFile::render', $this, 'renderInputfieldFile'); $this->addHookBefore('InputfieldFile(name^=language_files)::render', $this, 'renderInputfieldFile');
$this->addHookAfter('InputfieldFile::renderItem', $this, 'renderInputfieldFileItem'); $this->addHookAfter('InputfieldFile::renderItem', $this, 'renderInputfieldFileItem');
$this->addHookAfter('InputfieldFile::renderUpload', $this, 'renderInputfieldFileUpload'); $this->addHookAfter('InputfieldFile::renderUpload', $this, 'renderInputfieldFileUpload');
$this->addHookBefore('InputfieldFile::processInput', $this, 'processInputfieldFileInput'); $this->addHookBefore('InputfieldFile::processInput', $this, 'processInputfieldFileInput');
@@ -647,4 +656,3 @@ class ProcessLanguage extends ProcessPageType {
$translator->unloadTextdomain($textdomain); $translator->unloadTextdomain($textdomain);
} }
} }

View File

@@ -167,8 +167,8 @@ class LazyCron extends WireData implements Module {
} }
} }
if(!$files->filePutContents($this->lockfile, time(), LOCK_EX)) { if(!$files->filePutContents($this->lockfile, (string) time(), LOCK_EX)) {
$this->error("Unable to write lock file: $this->lockfile", Notice::logOnly); // $this->error("Unable to write lock file: $this->lockfile", Notice::logOnly);
return; return;
} }

View File

@@ -5,7 +5,7 @@ require_once(dirname(__FILE__) . '/PagerNav.php');
/** /**
* MarkupPagerNav Module for generating pagination markup * MarkupPagerNav Module for generating pagination markup
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* #pw-summary Module for generating pagination markup automatically for paginated WireArray types. * #pw-summary Module for generating pagination markup automatically for paginated WireArray types.
@@ -117,7 +117,7 @@ class MarkupPagerNav extends Wire implements Module {
'permanent' => false, 'permanent' => false,
'singular' => false, 'singular' => false,
'autoload' => false, 'autoload' => false,
); );
} }
/** /**
@@ -210,7 +210,7 @@ class MarkupPagerNav extends Wire implements Module {
// the queryString used in links (set automatically, based on whitelist or getVars array) // the queryString used in links (set automatically, based on whitelist or getVars array)
'queryString' => '', 'queryString' => '',
); );
/** /**
* True when the current page is also the last page * True when the current page is also the last page
@@ -229,10 +229,11 @@ class MarkupPagerNav extends Wire implements Module {
protected $pageNumUrlPrefix = 'page'; protected $pageNumUrlPrefix = 'page';
/** /**
* Construct * Wired to ProcessWire instance
* *
*/ */
public function __construct() { public function wired() {
parent::wired();
$this->options['nextItemLabel'] = $this->_('Next'); $this->options['nextItemLabel'] = $this->_('Next');
$this->options['previousItemLabel'] = $this->_('Prev'); $this->options['previousItemLabel'] = $this->_('Prev');
$this->options['listAriaLabel'] = $this->_('Pagination links'); $this->options['listAriaLabel'] = $this->_('Pagination links');
@@ -241,9 +242,9 @@ class MarkupPagerNav extends Wire implements Module {
$this->options['nextItemAriaLabel'] = $this->_('Next page'); $this->options['nextItemAriaLabel'] = $this->_('Next page');
$this->options['previousItemAriaLabel'] = $this->_('Previous page'); $this->options['previousItemAriaLabel'] = $this->_('Previous page');
$this->options['lastItemAriaLabel'] = $this->_('Page {n}, last page'); $this->options['lastItemAriaLabel'] = $this->_('Page {n}, last page');
// check for all-instance options // check for all-instance options
$options = $this->wire('config')->MarkupPagerNav; $options = $this->wire()->config->MarkupPagerNav;
if(is_array($options)) $this->options = array_merge($this->options, $options); if(is_array($options)) $this->options = array_merge($this->options, $options);
} }
@@ -270,7 +271,7 @@ class MarkupPagerNav extends Wire implements Module {
*/ */
public function ___render(WirePaginatable $items, $options = array()) { public function ___render(WirePaginatable $items, $options = array()) {
$config = $this->wire('config'); $config = $this->wire()->config;
$this->isLastPage = true; $this->isLastPage = true;
$this->totalItems = $items->getTotal(); $this->totalItems = $items->getTotal();
if(!$this->totalItems) return ''; if(!$this->totalItems) return '';
@@ -285,7 +286,7 @@ class MarkupPagerNav extends Wire implements Module {
} }
if(!strlen($this->queryString)) { if(!strlen($this->queryString)) {
$whitelist = $this->wire('input')->whitelist->getArray(); $whitelist = $this->wire()->input->whitelist->getArray();
if(!count($this->options['getVars']) && count($whitelist)) { if(!count($this->options['getVars']) && count($whitelist)) {
$this->setGetVars($whitelist); $this->setGetVars($whitelist);
} else if(count($this->options['getVars'])) { } else if(count($this->options['getVars'])) {
@@ -453,13 +454,13 @@ class MarkupPagerNav extends Wire implements Module {
/** /**
* Retrieve a MarkupPagerNav option as an object property * Retrieve a MarkupPagerNav option as an object property
* *
* @param string $property * @param string $name
* @return mixed * @return mixed
* *
*/ */
public function __get($property) { public function __get($name) {
if(isset($this->options[$property])) return $this->options[$property]; if(isset($this->options[$name])) return $this->options[$name];
if($property == 'isLastPage') return $this->isLastPage; if($name === 'isLastPage') return $this->isLastPage;
return null; return null;
} }
@@ -677,9 +678,8 @@ class MarkupPagerNav extends Wire implements Module {
*/ */
protected function updateConfigVars($nextURL, $prevURL) { protected function updateConfigVars($nextURL, $prevURL) {
/** @var Config $config */ $config = $this->wire()->config;
$config = $this->wire('config'); $httpRoot = $this->wire()->input->httpHostUrl();
$httpRoot = $this->wire('input')->httpHostUrl();
$pagerHeadTags = ''; $pagerHeadTags = '';
if($nextURL) { if($nextURL) {
@@ -705,4 +705,3 @@ class MarkupPagerNav extends Wire implements Module {
public function ___uninstall() { } public function ___uninstall() { }
} }

View File

@@ -141,7 +141,7 @@ class PagePaths extends WireData implements Module, ConfigurableModule {
$query->bindValue(":language_id", $languageId, \PDO::PARAM_INT); $query->bindValue(":language_id", $languageId, \PDO::PARAM_INT);
$path = null; $path = null;
if(!$this->executeQuery($query)) return $path; if(!$this->executeQuery($query)) return null;
if($query->rowCount()) { if($query->rowCount()) {
$path = $query->fetchColumn(); $path = $query->fetchColumn();
@@ -662,7 +662,7 @@ class PagePaths extends WireData implements Module, ConfigurableModule {
/** /**
* Returns Languages object or false if not available * Returns Languages object or false if not available
* *
* @return Languages|false * @return Languages|Language[]|false
* *
*/ */
public function getLanguages() { public function getLanguages() {

View File

@@ -252,7 +252,6 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function ___clearCacheFilePages(PageArray $items, Page $page) { public function ___clearCacheFilePages(PageArray $items, Page $page) {
if($page) {}
foreach($items as $p) { foreach($items as $p) {
if(((int) $p->template->cache_time) < 1) continue; if(((int) $p->template->cache_time) < 1) continue;
$cf = $this->getCacheFile($p); $cf = $this->getCacheFile($p);
@@ -357,7 +356,6 @@ class PageRender extends WireData implements Module, ConfigurableModule {
* *
*/ */
public function ___saveCacheFileReady(Page $page, $data) { public function ___saveCacheFileReady(Page $page, $data) {
if($page) {} // ignore
return $data; return $data;
} }
@@ -570,6 +568,7 @@ class PageRender extends WireData implements Module, ConfigurableModule {
// own additional variables in it if they want to // own additional variables in it if they want to
$output->set('options', $options); $output->set('options', $options);
/** @var WireProfilerInterface $profiler */
$profiler = $this->wire('profiler'); $profiler = $this->wire('profiler');
$profilerEvent = $profiler ? $profiler->start($page->path, $this, array('page' => $page)) : null; $profilerEvent = $profiler ? $profiler->start($page->path, $this, array('page' => $page)) : null;
$data = $output->render(); $data = $output->render();

View File

@@ -1216,7 +1216,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
public function getSelectorTemplates($selector, $getArray = true) { public function getSelectorTemplates($selector, $getArray = true) {
$return = $getArray ? array() : ''; $return = $getArray ? array() : '';
$templates = array(); $templates = array();
if(stripos($selector, 'template=') === false) return $return; if(stripos("$selector", 'template=') === false) return $return;
if(!preg_match('/(?:^|[^.])\btemplate=([^,]+)/i', $selector, $matches)) return $return; if(!preg_match('/(?:^|[^.])\btemplate=([^,]+)/i', $selector, $matches)) return $return;
if(!$getArray) return $matches[1]; // return pipe separated string if(!$getArray) return $matches[1]; // return pipe separated string
$template = explode('|', $matches[1]); $template = explode('|', $matches[1]);
@@ -1297,6 +1297,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
$sanitizer = $this->wire()->sanitizer; $sanitizer = $this->wire()->sanitizer;
$modules = $this->wire()->modules; $modules = $this->wire()->modules;
$fields = $this->wire()->fields; $fields = $this->wire()->fields;
$adminTheme = $this->wire()->adminTheme;
/** @var Languages $languages */ /** @var Languages $languages */
$columns = $this->sessionGet('columns'); $columns = $this->sessionGet('columns');
@@ -1307,7 +1308,7 @@ class ProcessPageLister extends Process implements ConfigurableModule {
/** @var MarkupAdminDataTable $table */ /** @var MarkupAdminDataTable $table */
$table = $modules->get('MarkupAdminDataTable'); $table = $modules->get('MarkupAdminDataTable');
$table->setSortable(false); $table->setSortable(false);
$table->setResizable(true); $table->setResizable(wireInstanceOf($adminTheme, 'AdminThemeUikit')); // non-100% width error w/default+reno themes
$table->setResponsive($this->responsiveTable); $table->setResponsive($this->responsiveTable);
$table->setClass('ProcessListerTable'); $table->setClass('ProcessListerTable');
$table->setEncodeEntities(false); $table->setEncodeEntities(false);

View File

@@ -5,7 +5,7 @@
* *
* Formats text with PHP's htmlspecialchars() function. * Formats text with PHP's htmlspecialchars() function.
* *
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer * ProcessWire 3.x, Copyright 2023 by Ryan Cramer
* https://processwire.com * https://processwire.com
* *
* *
@@ -20,11 +20,15 @@ class TextformatterEntities extends Textformatter {
'version' => 100, 'version' => 100,
); );
} }
protected $charset = '';
public function format(&$str) { public function format(&$str) {
static $charset = false; if($this->charset === '') $this->charset = $this->wire()->config->dbCharset;
if($charset === false) $charset = $this->config->dbCharset; if(stripos($this->charset, 'utf8') === 0) {
if($charset == 'utf8') $str = htmlspecialchars($str, ENT_QUOTES, "UTF-8"); $str = htmlspecialchars($str, ENT_QUOTES, 'UTF-8');
else $str = htmlspecialchars($str, ENT_QUOTES); } else {
$str = htmlspecialchars($str, ENT_QUOTES);
}
} }
} }

View File

@@ -98,7 +98,8 @@ class TextformatterSmartypants extends Textformatter implements ConfigurableModu
* *
*/ */
public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { public function getModuleConfigInputfields(InputfieldWrapper $inputfields) {
$f = $this->wire('modules')->get('InputfieldRadios'); /** @var InputfieldRadios $f */
$f = $this->wire()->modules->get('InputfieldRadios');
$f->attr('name', 'useUTF8'); $f->attr('name', 'useUTF8');
$f->label = $this->_('Use UTF-8 characters for replacements rather than HTML entities?'); $f->label = $this->_('Use UTF-8 characters for replacements rather than HTML entities?');
$f->description = $this->_('The default behavior for SmartyPants is to add/update characters using HTML entities.') . ' '; $f->description = $this->_('The default behavior for SmartyPants is to add/update characters using HTML entities.') . ' ';

View File

@@ -33,14 +33,15 @@ class TextformatterStripTags extends Textformatter implements ConfigurableModule
$inputfields = $this->wire(new InputfieldWrapper()); $inputfields = $this->wire(new InputfieldWrapper());
$name = "allowedTags"; $name = "allowedTags";
if(!isset($data[$name])) $data[$name] = ''; if(!isset($data[$name])) $data[$name] = '';
$f = $this->wire('modules')->get('InputfieldText'); /** @var InputfieldText $f */
$f = $this->wire()->modules->get('InputfieldText');
$f->attr('name', $name); $f->attr('name', $name);
$f->attr('value', $data[$name]); $f->attr('value', $data[$name]);
$f->label = 'Allowed Markup Tags'; $f->label = 'Allowed Markup Tags';
$f->description = $f->description =
"Enter any markup tags that are allowed, i.e. '<strong><em>'. " . "Enter any markup tags that are allowed, i.e. `<strong><em>`. " .
"Note that this does not strip attributes for any tags you allow. " . "Note that this does not strip attributes for any tags you allow. " .
"As a result, you should not allow *any* tags unless the user is trusted."; "As a result, you should not allow *any* tags unless all potential users are trusted.";
$inputfields->append($f); $inputfields->append($f);
return $inputfields; return $inputfields;
} }