mirror of
https://github.com/processwire/processwire.git
synced 2025-08-11 09:14:58 +02:00
Merge recent changes from devns branch
This commit is contained in:
@@ -555,6 +555,35 @@ $config->adminThumbOptions = array(
|
||||
'suffix' => '',
|
||||
);
|
||||
|
||||
/**
|
||||
* File compiler options (as used by FileCompiler class)
|
||||
*
|
||||
* Enables modification of file compiler behaviors. See also $config->moduleCompile
|
||||
* and $config->templateCompile settings.
|
||||
*
|
||||
* #property bool siteOnly Specify true to prevent compiler from attempting compilation outside files in /site/ (default=false).
|
||||
* #property bool showNotices Show notices in admin about compiled files to superuser when logged in (default=true).
|
||||
* #property bool logNotices Log notices about compiled files and maintenance to file-compiler.txt log (default=true).
|
||||
* #property string chmodFile Mode to use for created files, i.e. "0644" (uses $config->chmodFile setting by default).
|
||||
* #property string chmodDir Mode to use for created dirs, i.e. "0755" (uses $config->chmodDir setting by default).
|
||||
* #property array exclusions Exclude paths that exist within any of these paths (default includes $config->paths->wire).
|
||||
* #property array extensions File extensions that we compile (default=php, module, inc).
|
||||
* #property string cachePath Path where compiled files are stored (default is $config->paths->cache . 'FileCompiler/')
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
$config->fileCompilerOptions = array(
|
||||
'siteOnly' => false, // only allow compilation of files in /site/ directory
|
||||
'showNotices' => true, // show notices about compiled files to superuser when logged in
|
||||
'logNotices' => true, // log notices about compiled files and maintenance to file-compiler.txt log.
|
||||
'chmodFile' => $config->chmodFile, // mode to use for created files, i.e. "0644"
|
||||
'chmodDir' => $config->chmodDir, // mode to use for created directories, i.e. "0755"
|
||||
'exclusions' => array(), // exclude filenames or paths that start with any of these
|
||||
'extensions' => array('php', 'module', 'inc'), // file extensions we compile
|
||||
'cachePath' => $config->paths->cache . 'FileCompiler/', // path where compiled files are stored
|
||||
);
|
||||
|
||||
/**
|
||||
* Temporary directory for uploads
|
||||
*
|
||||
@@ -1023,9 +1052,13 @@ $config->preloadCacheNames = array(
|
||||
$config->allowExceptions = false;
|
||||
|
||||
/**
|
||||
* Use the X-Powered-By header?
|
||||
* X-Powered-By header behavior
|
||||
*
|
||||
* - true: Sends the generic PW header, replacing any other powered-by headers (recommended).
|
||||
* - false: Sends blank powered-by, replacing any other powered-by headers.
|
||||
* - null: Sends no powered-by, existing server powered-by headers will pass through.
|
||||
*
|
||||
* @var bool
|
||||
* @var bool|null
|
||||
*
|
||||
*/
|
||||
$config->usePoweredBy = true;
|
||||
|
@@ -40,6 +40,7 @@
|
||||
*
|
||||
* @property array $contentTypes Array of extensions and the associated MIME type for each (for template file output). #pw-group-template-files
|
||||
* @property array $fileContentTypes Array of extensions and the associated MIME type for each (for file output). See /wire/config.php for details and defaults. #pw-group-files
|
||||
* @property array $fileCompilerOptions Array of options for FileCompiler class. See /wire/config.php for details and defaults. #pw-group-files
|
||||
*
|
||||
* @property string $chmodDir Octal string permissions assigned to directories created by ProcessWire #pw-group-files
|
||||
* @property string $chmodFile Octal string permissions assigned to files created by ProcessWire #pw-group-files
|
||||
@@ -301,5 +302,71 @@ class Config extends WireData {
|
||||
$this->jsFields[] = $key;
|
||||
return parent::set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allow for getting/setting config properties via method call
|
||||
*
|
||||
* This is primarily useful for getting or setting config properties that consist of associative arrays.
|
||||
*
|
||||
* ~~~~~
|
||||
*
|
||||
* // Enable debug mode, same as $config->debug = true;
|
||||
* $config->debug(true);
|
||||
*
|
||||
* // Set a specific property in options array
|
||||
* $config->fileCompilerOptions('siteOnly', true);
|
||||
*
|
||||
* // Get a specific property in options array
|
||||
* $value = $config->fileCompilerOptions('siteOnly');
|
||||
*
|
||||
* // Set multiple properties in options array (leaving other existing properties alone)
|
||||
* $config->fileCompilerOptions([
|
||||
* 'siteOnly' => true,
|
||||
* 'cachePath' => $config->paths->root . '.my-cache/'
|
||||
* ]);
|
||||
* ~~~~~
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @param string $method Requested method name
|
||||
* @param array $arguments Arguments provided
|
||||
* @return null|mixed Return value of method (if applicable)
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
protected function ___callUnknown($method, $arguments) {
|
||||
//$this->message("callUnknown($method)");
|
||||
$value = parent::get($method);
|
||||
if($value === null) return parent::___callUnknown($method, $arguments);
|
||||
$numArgs = count($arguments);
|
||||
if($numArgs === 0) return $value; // no arguments? just return value
|
||||
|
||||
if(is_array($value)) {
|
||||
// existing value is an array
|
||||
$property = $arguments[0];
|
||||
if($numArgs === 1) {
|
||||
// just a property name (get) or array (set) provided
|
||||
if(is_string($property)) {
|
||||
// just return property value from array
|
||||
return isset($value[$property]) ? $value[$property] : null;
|
||||
} else if(is_array($property)) {
|
||||
// set multiple named properties
|
||||
$value = array_merge($value, $property);
|
||||
parent::set($method, $value);
|
||||
} else {
|
||||
throw new WireException("Invalid argument, array or string expected");
|
||||
}
|
||||
} else {
|
||||
// property and value provided
|
||||
$value[$property] = $arguments[1];
|
||||
parent::set($method, $value);
|
||||
}
|
||||
} else if($numArgs === 1) {
|
||||
// just set a value
|
||||
parent::set($method, $arguments[0]);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -480,7 +480,7 @@ class Fields extends WireSaveableItems {
|
||||
|
||||
foreach($schema1 as $key => $value) {
|
||||
if(!in_array($value, $schema2)) {
|
||||
if($this->config->debug) $this->message("changeFieldType loses table field '$value'");
|
||||
if($this->wire('config')->debug) $this->message("changeFieldType loses table field '$value'");
|
||||
unset($schema1[$key]);
|
||||
}
|
||||
}
|
||||
|
@@ -14,7 +14,7 @@
|
||||
class FileCompiler extends Wire {
|
||||
|
||||
/**
|
||||
* Compilation options
|
||||
* Compilation options for this FileCompiler instance
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
@@ -25,6 +25,25 @@ class FileCompiler extends Wire {
|
||||
'modules' => false, // compile using installed FileCompiler modules
|
||||
'skipIfNamespace' => false, // skip compiled file if original declares a namespace? (note: file still compiled, but not used)
|
||||
);
|
||||
|
||||
/**
|
||||
* Options for ALL FileCompiler instances
|
||||
*
|
||||
* Values shown below are for reference only as the get overwritten by $config->fileCompilerOptions at runtime.
|
||||
*
|
||||
* @var array
|
||||
*
|
||||
*/
|
||||
protected $globalOptions = array(
|
||||
'siteOnly' => false, // only allow compilation of files in /site/ directory
|
||||
'showNotices' => true, // show notices about compiled files to superuser
|
||||
'logNotices' => true, // log notices about compiled files and maintenance to file-compiler.txt log.
|
||||
'chmodFile' => '', // mode to use for created files, i.e. "0644"
|
||||
'chmodDir' => '', // mode to use for created directories, i.e. "0755"
|
||||
'exclusions' => array(), // exclude files or paths that start with any of these (gets moved to $this->exclusions array)
|
||||
'extensions' => array('php', 'module', 'inc'), // file extensions we compile (gets moved to $this->extensions array)
|
||||
'cachePath' => '', // path where compiled files are stored (default is /site/assets/cache/FileCompiler/, moved to $this->cachePath)
|
||||
);
|
||||
|
||||
/**
|
||||
* Path to source files directory
|
||||
@@ -42,6 +61,16 @@ class FileCompiler extends Wire {
|
||||
*/
|
||||
protected $targetPath = null;
|
||||
|
||||
/**
|
||||
* Path to root of compiled files directory (upon which targetPath is based)
|
||||
*
|
||||
* Set via the $config->fileCompilerOptions['cachePath'] setting.
|
||||
*
|
||||
* @var string
|
||||
*
|
||||
*/
|
||||
protected $cachePath;
|
||||
|
||||
/**
|
||||
* Files or directories that should be excluded from compilation
|
||||
*
|
||||
@@ -78,12 +107,30 @@ class FileCompiler extends Wire {
|
||||
*
|
||||
*/
|
||||
public function __construct($sourcePath, array $options = array()) {
|
||||
|
||||
$this->options = array_merge($this->options, $options);
|
||||
$globalOptions = $this->wire('config')->fileCompilerOptions;
|
||||
|
||||
if(is_array($globalOptions)) {
|
||||
$this->globalOptions = array_merge($this->globalOptions, $globalOptions);
|
||||
}
|
||||
|
||||
if(!empty($this->globalOptions['extensions'])) {
|
||||
$this->extensions = $this->globalOptions['extensions'];
|
||||
}
|
||||
|
||||
if(empty($this->globalOptions['cachePath'])) {
|
||||
$this->cachePath = $this->wire('config')->paths->cache . $this->className() . '/';
|
||||
} else {
|
||||
$this->cachePath = rtrim($this->globalOptions['cachePath'], '/') . '/';
|
||||
}
|
||||
|
||||
if(!strlen(__NAMESPACE__)) {
|
||||
// when PW compiled without namespace support
|
||||
$this->options['skipIfNamespace'] = false;
|
||||
$this->options['namespace'] = true;
|
||||
}
|
||||
|
||||
if(strpos($sourcePath, '..') !== false) $sourcePath = realpath($sourcePath);
|
||||
if(DIRECTORY_SEPARATOR != '/') $sourcePath = str_replace(DIRECTORY_SEPARATOR, '/', $sourcePath);
|
||||
$this->sourcePath = rtrim($sourcePath, '/') . '/';
|
||||
@@ -98,29 +145,59 @@ class FileCompiler extends Wire {
|
||||
protected function init() {
|
||||
|
||||
static $preloaded = false;
|
||||
$config = $this->wire('config');
|
||||
|
||||
if(!$preloaded) {
|
||||
$this->wire('cache')->preloadFor($this);
|
||||
$preloaded = true;
|
||||
}
|
||||
|
||||
$targetPath = $this->wire('config')->paths->cache . $this->className() . '/';
|
||||
if(!empty($this->globalOptions['exclusions'])) {
|
||||
$this->exclusions = $this->globalOptions['exclusions'];
|
||||
}
|
||||
|
||||
$this->addExclusion($config->paths->wire);
|
||||
|
||||
$rootPath = $config->paths->root;
|
||||
$targetPath = $this->cachePath;
|
||||
|
||||
if(strpos($this->sourcePath, $targetPath) === 0) {
|
||||
// sourcePath is inside the targetPath, correct this
|
||||
$this->sourcePath = str_replace($targetPath, '', $this->sourcePath);
|
||||
$this->sourcePath = $this->wire('config')->paths->root . $this->sourcePath;
|
||||
$this->sourcePath = $rootPath . $this->sourcePath;
|
||||
}
|
||||
|
||||
$t = str_replace($this->wire('config')->paths->root, '', $this->sourcePath);
|
||||
|
||||
$t = str_replace($rootPath, '', $this->sourcePath);
|
||||
if(DIRECTORY_SEPARATOR != '/' && strpos($t, ':')) $t = str_replace(':', '', $t);
|
||||
$this->targetPath = $targetPath . trim($t, '/') . '/';
|
||||
|
||||
// @todo move this somewhere outside of this class
|
||||
$this->addExclusion($this->wire('config')->paths->wire);
|
||||
// $this->addExclusion($this->wire('config')->paths->templates . 'admin.php');
|
||||
|
||||
$this->ns = '';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a directory with proper permissions
|
||||
*
|
||||
* @param string $path Path of directory to create
|
||||
* @param bool $recursive Default is true
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function mkdir($path, $recursive = true) {
|
||||
$chmod = $this->globalOptions['chmodDir'];
|
||||
if(empty($chmod) || !is_string($chmod) || strlen($chmod) < 2) $chmod = null;
|
||||
return $this->wire('files')->mkdir($path, $recursive, $chmod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change file to correct mode for FileCompiler
|
||||
*
|
||||
* @param string $filename
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function chmod($filename) {
|
||||
$chmod = $this->globalOptions['chmodFile'];
|
||||
if(empty($chmod) || !is_string($chmod) || strlen($chmod) < 2) $chmod = null;
|
||||
return $this->wire('files')->chmod($filename, false, $chmod);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +208,7 @@ class FileCompiler extends Wire {
|
||||
*/
|
||||
protected function initTargetPath() {
|
||||
if(!is_dir($this->targetPath)) {
|
||||
if(!$this->wire('files')->mkdir($this->targetPath, true)) {
|
||||
if(!$this->mkdir($this->targetPath)) {
|
||||
throw new WireException("Unable to create directory $this->targetPath");
|
||||
}
|
||||
}
|
||||
@@ -140,13 +217,21 @@ class FileCompiler extends Wire {
|
||||
/**
|
||||
* Allow the given filename to be compiled?
|
||||
*
|
||||
* @param string $filename This property can be modified by the function
|
||||
* @param string $basename This property can be modified by the function
|
||||
* @param string $filename Full path and filename to compile (this property can be modified by the function).
|
||||
* @param string $basename Just the basename (this property can be modified by the function).
|
||||
* @return bool
|
||||
*
|
||||
*/
|
||||
protected function allowCompile(&$filename, &$basename) {
|
||||
|
||||
if($this->globalOptions['siteOnly']) {
|
||||
// only files in /site/ are allowed for compilation
|
||||
if(strpos($filename, $this->wire('config')->paths->site) !== 0) {
|
||||
// sourcePath is somewhere outside of the PW /site/, and not allowed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
if(!in_array(strtolower($ext), $this->extensions)) {
|
||||
if(!strlen($ext) && !is_file($filename)) {
|
||||
@@ -237,10 +322,10 @@ class FileCompiler extends Wire {
|
||||
set_time_limit(120);
|
||||
$this->copyAllNewerFiles($sourcePath, $targetPath);
|
||||
$targetDirname = dirname($targetPathname) . '/';
|
||||
if(!is_dir($targetDirname)) $this->wire('files')->mkdir($targetDirname, true);
|
||||
if(!is_dir($targetDirname)) $this->mkdir($targetDirname);
|
||||
$targetData = $this->compileData($targetData, $sourcePathname);
|
||||
if(false !== file_put_contents($targetPathname, $targetData, LOCK_EX)) {
|
||||
$this->wire('files')->chmod($targetPathname);
|
||||
$this->chmod($targetPathname);
|
||||
touch($targetPathname, filemtime($sourcePathname));
|
||||
$targetHash = md5_file($targetPathname);
|
||||
$cacheData = array(
|
||||
@@ -260,14 +345,24 @@ class FileCompiler extends Wire {
|
||||
);
|
||||
$this->wire('cache')->saveFor($this, $cacheName, $cacheData, WireCache::expireNever);
|
||||
}
|
||||
$u = $this->wire('user');
|
||||
if($this->wire('config')->debug || ($u && $u->isSuperuser())) {
|
||||
$this->message($this->_('Compiled file:') . ' ' . str_replace($this->wire('config')->paths->root, '/', $sourcePathname));
|
||||
}
|
||||
}
|
||||
|
||||
// if source and target are identical, use the source file
|
||||
if($targetHash && $sourceHash === $targetHash) return $sourcePathname;
|
||||
if($targetHash && $sourceHash === $targetHash) {
|
||||
return $sourcePathname;
|
||||
}
|
||||
|
||||
// show notices about compiled files, when applicable
|
||||
if($compileNow) {
|
||||
$message = $this->_('Compiled file:') . ' ' . str_replace($this->wire('config')->paths->root, '/', $sourcePathname);
|
||||
if($this->globalOptions['showNotices']) {
|
||||
$u = $this->wire('user');
|
||||
if($u && $u->isSuperuser()) $this->message($message);
|
||||
}
|
||||
if($this->globalOptions['logNotices']) {
|
||||
$this->log($message);
|
||||
}
|
||||
}
|
||||
|
||||
// if source file declares a namespace and skipIfNamespace option in use, use source file
|
||||
if($this->options['skipIfNamespace'] && $this->ns && $this->ns != "\\") return $sourcePathname;
|
||||
@@ -747,7 +842,7 @@ class FileCompiler extends Wire {
|
||||
}
|
||||
|
||||
copy($sourceFile, $targetFile);
|
||||
$this->wire('files')->chmod($targetFile);
|
||||
$this->chmod($targetFile);
|
||||
touch($targetFile, filemtime($sourceFile));
|
||||
$numCopied++;
|
||||
}
|
||||
@@ -772,7 +867,7 @@ class FileCompiler extends Wire {
|
||||
if(!is_null($targetPath)) {
|
||||
// use it
|
||||
} else if($all) {
|
||||
$targetPath = $this->wire('config')->paths->cache . $this->className() . '/';
|
||||
$targetPath = $this->cachePath;
|
||||
} else {
|
||||
$this->init();
|
||||
$targetPath = $this->targetPath;
|
||||
@@ -803,7 +898,7 @@ class FileCompiler extends Wire {
|
||||
*/
|
||||
public function clearCache($all = false) {
|
||||
if($all) {
|
||||
$targetPath = $this->wire('config')->paths->cache . $this->className() . '/';
|
||||
$targetPath = $this->cachePath;
|
||||
$this->wire('cache')->deleteFor($this);
|
||||
} else {
|
||||
$this->init();
|
||||
@@ -832,7 +927,7 @@ class FileCompiler extends Wire {
|
||||
return false;
|
||||
}
|
||||
touch($lastRunFile);
|
||||
$this->wire('files')->chmod($lastRunFile);
|
||||
$this->chmod($lastRunFile);
|
||||
clearstatcache();
|
||||
|
||||
return $this->_maintenance($this->sourcePath, $this->targetPath);
|
||||
@@ -854,6 +949,7 @@ class FileCompiler extends Wire {
|
||||
$targetPath = rtrim($targetPath, '/') . '/';
|
||||
$sourceURL = str_replace($this->wire('config')->paths->root, '/', $sourcePath);
|
||||
$targetURL = str_replace($this->wire('config')->paths->root, '/', $targetPath);
|
||||
$useLog = $this->globalOptions['logNotices'];
|
||||
|
||||
//$this->log("Running maintenance for $targetURL (source: $sourceURL)");
|
||||
|
||||
@@ -871,7 +967,7 @@ class FileCompiler extends Wire {
|
||||
if($file->isDir()) {
|
||||
if(!is_dir($sourceFile)) {
|
||||
$this->wire('files')->rmdir($targetFile, true);
|
||||
$this->log("Remove directory: $targetURL$basename");
|
||||
if($useLog) $this->log("Maintenance/Remove directory: $targetURL$basename");
|
||||
} else {
|
||||
$this->_maintenance($sourceFile, $targetFile);
|
||||
}
|
||||
@@ -881,14 +977,14 @@ class FileCompiler extends Wire {
|
||||
if(!file_exists($sourceFile)) {
|
||||
// source file has been deleted
|
||||
unlink($targetFile);
|
||||
$this->log("Remove target file: $targetURL$basename");
|
||||
if($useLog) $this->log("Maintenance/Remove target file: $targetURL$basename");
|
||||
|
||||
} else if(filemtime($sourceFile) != filemtime($targetFile)) {
|
||||
// source file has changed
|
||||
copy($sourceFile, $targetFile);
|
||||
$this->wire('files')->chmod($targetFile);
|
||||
$this->chmod($targetFile);
|
||||
touch($targetFile, filemtime($sourceFile));
|
||||
$this->log("Copy new version of source file to target file: $sourceURL$basename => $targetURL$basename");
|
||||
if($useLog) $this->log("Maintenance/Copy new version of source file to target file: $sourceURL$basename => $targetURL$basename");
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1330,9 +1330,12 @@ class Modules extends WireArray {
|
||||
|
||||
// attempt to retrieve module
|
||||
$module = parent::get($moduleName);
|
||||
if($module && !$module instanceof Module) return false;
|
||||
|
||||
if($module) {
|
||||
// module found, check to make sure it actually points to a module
|
||||
if(!$module instanceof Module) $module = false;
|
||||
|
||||
if(!$module && $moduleName) {
|
||||
} else if($moduleName) {
|
||||
// unable to retrieve module, may be an uninstalled module
|
||||
if(!$file) {
|
||||
$file = $this->getModuleFile($moduleName, array('fast' => true));
|
||||
@@ -1340,9 +1343,16 @@ class Modules extends WireArray {
|
||||
}
|
||||
if($file) {
|
||||
$this->includeModuleFile($file, $moduleName);
|
||||
if(class_exists($className, false)) {
|
||||
// successful include module
|
||||
$module = true;
|
||||
// now check to see if included file resulted in presence of module class
|
||||
if(class_exists($className)) {
|
||||
$module = true;
|
||||
} else {
|
||||
if(!$namespace) $namespace = $this->getModuleNamespace($moduleName, array('file' => $file));
|
||||
$nsClassName = trim($namespace, "\\") . "\\$moduleName";
|
||||
if(class_exists($nsClassName, false)) {
|
||||
// successful include module
|
||||
$module = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1396,8 +1406,10 @@ class Modules extends WireArray {
|
||||
// get compiled version (if it needs compilation)
|
||||
$file = $this->compile($moduleName, $file);
|
||||
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($file);
|
||||
if($file) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($file);
|
||||
}
|
||||
|
||||
// set instance back, if multi-instance
|
||||
if($wire1 !== $wire2) ProcessWire::setCurrentInstance($wire1);
|
||||
@@ -3185,8 +3197,10 @@ class Modules extends WireArray {
|
||||
} else {
|
||||
$ns = $this->getFileNamespace($file);
|
||||
$file = $this->compile($className, $file, $ns);
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($file);
|
||||
if($file) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!is_null($config)) {
|
||||
@@ -3324,8 +3338,10 @@ class Modules extends WireArray {
|
||||
if(!class_exists($className, false)) {
|
||||
$configFile = $this->compile($className, $configurable);
|
||||
// $configFile = $compile ? $this->wire('files')->compile($configurable) : $configurable;
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($configFile);
|
||||
if($configFile) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($configFile);
|
||||
}
|
||||
}
|
||||
|
||||
if(wireClassExists($className)) {
|
||||
@@ -3345,8 +3361,10 @@ class Modules extends WireArray {
|
||||
$configFile = $this->compile($className, $configurable);
|
||||
// $configFile = $compile ? $this->wire('files')->compile($configurable) : $configurable;
|
||||
}
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($configFile);
|
||||
if($configFile) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($configFile);
|
||||
}
|
||||
}
|
||||
if(is_array($config)) {
|
||||
// alternatively, file may just specify a $config array
|
||||
@@ -3510,8 +3528,10 @@ class Modules extends WireArray {
|
||||
$configClass = $ns . $moduleName . "Config";
|
||||
if(!class_exists($configClass)) {
|
||||
$configFile = $this->compile($moduleName, $file, $ns);
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($configFile);
|
||||
if($configFile) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include_once($configFile);
|
||||
}
|
||||
}
|
||||
$configModule = null;
|
||||
|
||||
@@ -3523,8 +3543,10 @@ class Modules extends WireArray {
|
||||
if(is_null($config)) {
|
||||
$configFile = $this->compile($moduleName, $file, $ns);
|
||||
// if(!$configFile) $configFile = $compile ? $this->wire('files')->compile($file) : $file;
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($configFile); // in case of previous include_once
|
||||
if($configFile) {
|
||||
/** @noinspection PhpIncludeInspection */
|
||||
include($configFile); // in case of previous include_once
|
||||
}
|
||||
}
|
||||
if(is_array($config)) {
|
||||
// file contains a $config array
|
||||
@@ -4591,16 +4613,16 @@ class Modules extends WireArray {
|
||||
* @param Module|string $moduleName
|
||||
* @param string $file Optionally specify the module filename as an optimization
|
||||
* @param string|null $namespace Optionally specify namespace as an optimization
|
||||
* @return bool
|
||||
* @return string|bool
|
||||
*
|
||||
*/
|
||||
public function compile($moduleName, $file = '', $namespace = null) {
|
||||
|
||||
// don't compile when module compilation is disabled
|
||||
if(!$this->wire('config')->moduleCompile) return false;
|
||||
|
||||
|
||||
// if not given a file, track it down
|
||||
if(empty($file)) $file = $this->getModuleFile($moduleName);
|
||||
|
||||
// don't compile when module compilation is disabled
|
||||
if(!$this->wire('config')->moduleCompile) return $file;
|
||||
|
||||
// don't compile core modules
|
||||
if(strpos($file, $this->coreModulesDir) !== false) return $file;
|
||||
|
@@ -182,7 +182,8 @@ class Password extends Wire {
|
||||
$rawLength = (int) ($requiredLength * 3 / 4 + 1);
|
||||
|
||||
if(function_exists('mcrypt_create_iv')) {
|
||||
$buffer = mcrypt_create_iv($rawLength, MCRYPT_DEV_URANDOM);
|
||||
// @operator added for PHP 7.1 which throws deprecated notice on this function call
|
||||
$buffer = @mcrypt_create_iv($rawLength, MCRYPT_DEV_URANDOM);
|
||||
if($buffer) $valid = true;
|
||||
}
|
||||
|
||||
|
@@ -2321,6 +2321,7 @@ class Sanitizer extends Wire {
|
||||
'templateName',
|
||||
'pageName',
|
||||
'pageNameTranslate',
|
||||
'pageNameUTF8',
|
||||
'filename',
|
||||
'path',
|
||||
'pagePathName',
|
||||
|
@@ -388,7 +388,7 @@ class Template extends WireData implements Saveable, Exportable {
|
||||
$has = in_array($rolePage->id, $this->editRoles);
|
||||
} else if($type === 'create') {
|
||||
$has = in_array($rolePage->id, $this->createRoles);
|
||||
} else if($tye == 'add') {
|
||||
} else if($type == 'add') {
|
||||
$has = in_array($rolePage->id, $this->addRoles);
|
||||
}
|
||||
return $has;
|
||||
|
@@ -368,8 +368,13 @@ abstract class Wire implements WireTranslatable, WireFuelable, WireTrackable {
|
||||
*
|
||||
*/
|
||||
public function __call($method, $arguments) {
|
||||
$result = $this->wire('hooks')->runHooks($this, $method, $arguments);
|
||||
if(!$result['methodExists'] && !$result['numHooksRun']) return $this->callUnknown($method, $arguments);
|
||||
$hooks = $this->wire('hooks');
|
||||
if($hooks) {
|
||||
$result = $hooks->runHooks($this, $method, $arguments);
|
||||
if(!$result['methodExists'] && !$result['numHooksRun']) return $this->callUnknown($method, $arguments);
|
||||
} else {
|
||||
return $this->___callUnknown($method, $arguments);
|
||||
}
|
||||
return $result['return'];
|
||||
}
|
||||
|
||||
@@ -406,7 +411,8 @@ abstract class Wire implements WireTranslatable, WireFuelable, WireTrackable {
|
||||
*/
|
||||
protected function ___callUnknown($method, $arguments) {
|
||||
if($arguments) {} // intentional to avoid unused argument notice
|
||||
if($this->wire('config')->disableUnknownMethodException) return null;
|
||||
$config = $this->wire('config');
|
||||
if($config && $config->disableUnknownMethodException) return null;
|
||||
throw new WireException("Method " . $this->className() . "::$method does not exist or is not callable in this context");
|
||||
}
|
||||
|
||||
@@ -1540,6 +1546,7 @@ abstract class Wire implements WireTranslatable, WireFuelable, WireTrackable {
|
||||
// this object has not yet been wired! use last known current instance as fallback
|
||||
// note this condition is unsafe in multi-instance mode
|
||||
$wire = ProcessWire::getCurrentInstance();
|
||||
if(!$wire) return null;
|
||||
|
||||
// For live hunting objects that are using the fallback, uncomment the following:
|
||||
// echo "<hr /><p>Non-wired object: '$name' in " . get_class($this) . ($value ? " (value=$value)" : "") . "</p>";
|
||||
|
@@ -710,4 +710,25 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
||||
return $backups;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get max length allowed for a fully indexed varchar column in ProcessWire
|
||||
*
|
||||
* #pw-internal
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
*/
|
||||
public function getMaxIndexLength() {
|
||||
$config = $this->wire('config');
|
||||
$engine = strtolower($config->dbEngine);
|
||||
$charset = strtolower($config->dbCharset);
|
||||
$max = 250;
|
||||
if($charset == 'utf8mb4') {
|
||||
if($engine == 'innodb') {
|
||||
$max = 191;
|
||||
}
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,6 +21,8 @@ class WireFileTools extends Wire {
|
||||
* setting `$config->chmodDir`, and it can create directories recursively. Meaning, if you want to create directory /a/b/c/
|
||||
* and directory /a/ doesn't yet exist, this method will take care of creating /a/, /a/b/, and /a/b/c/.
|
||||
*
|
||||
* The `$recursive` and `$chmod` arguments may optionally be swapped (since 3.0.34).
|
||||
*
|
||||
* ~~~~~
|
||||
* // Create a new directory in ProcessWire's cache dir
|
||||
* if($files->mkdir($config->paths->cache . 'foo-bar/')) {
|
||||
@@ -29,14 +31,22 @@ class WireFileTools extends Wire {
|
||||
* ~~~~~
|
||||
*
|
||||
* @param string $path Directory you want to create
|
||||
* @param bool $recursive If set to true, all directories will be created as needed to reach the end.
|
||||
* @param string $chmod Optional mode to set directory to (default: $config->chmodDir), format must be a string i.e. "0755"
|
||||
* @param bool|string $recursive If set to true, all directories will be created as needed to reach the end.
|
||||
* @param string|null|bool $chmod Optional mode to set directory to (default: $config->chmodDir), format must be a string i.e. "0755"
|
||||
* If omitted, then ProcessWire's `$config->chmodDir` setting is used instead.
|
||||
* @return bool True on success, false on failure
|
||||
*
|
||||
*/
|
||||
public function mkdir($path, $recursive = false, $chmod = null) {
|
||||
if(!strlen($path)) return false;
|
||||
|
||||
if(is_string($recursive) && strlen($recursive) > 2) {
|
||||
// chmod argument specified as $recursive argument or arguments swapped
|
||||
$_chmod = $recursive;
|
||||
$recursive = is_bool($chmod) ? $chmod : false;
|
||||
$chmod = $_chmod;
|
||||
}
|
||||
|
||||
if(!is_dir($path)) {
|
||||
if($recursive) {
|
||||
$parentPath = substr($path, 0, strrpos(rtrim($path, '/'), '/'));
|
||||
@@ -93,20 +103,29 @@ class WireFileTools extends Wire {
|
||||
* This method also provides the option of going recursive, adjusting the read/write mode for an entire
|
||||
* file/directory tree at once.
|
||||
*
|
||||
* The `$recursive` or `$chmod` arguments may be optionally swapped in order (since 3.0.34).
|
||||
*
|
||||
* ~~~~~
|
||||
* // Update the mode of /site/assets/cache/foo-bar/ recursively
|
||||
* $files->chmod($config->paths->cache . 'foo-bar/', true);
|
||||
* ~~~~~
|
||||
*
|
||||
* @param string $path Path or file that you want to adjust mode for (may be a path/directory or a filename).
|
||||
* @param bool $recursive If set to true, all files and directories in $path will be recursively set as well (default=false).
|
||||
* @param string If you want to set the mode to something other than ProcessWire's chmodFile/chmodDir settings,
|
||||
* @param bool|string $recursive If set to true, all files and directories in $path will be recursively set as well (default=false).
|
||||
* @param string|null|bool $chmod If you want to set the mode to something other than ProcessWire's chmodFile/chmodDir settings,
|
||||
* you may override it by specifying it here. Ignored otherwise. Format should be a string, like "0755".
|
||||
* @return bool Returns true if all changes were successful, or false if at least one chmod failed.
|
||||
* @throws WireException when it receives incorrect chmod format
|
||||
*
|
||||
*/
|
||||
public function chmod($path, $recursive = false, $chmod = null) {
|
||||
|
||||
if(is_string($recursive) && strlen($recursive) > 2) {
|
||||
// chmod argument specified as $recursive argument or arguments swapped
|
||||
$_chmod = $recursive;
|
||||
$recursive = is_bool($chmod) ? $chmod : false;
|
||||
$chmod = $_chmod;
|
||||
}
|
||||
|
||||
if(is_null($chmod)) {
|
||||
// default: pull values from PW config
|
||||
|
@@ -1,7 +1,7 @@
|
||||
DROP TABLE IF EXISTS `field_email`;
|
||||
CREATE TABLE `field_email` (
|
||||
`pages_id` int(10) unsigned NOT NULL,
|
||||
`data` varchar(255) NOT NULL default '',
|
||||
`data` varchar(250) NOT NULL default '',
|
||||
PRIMARY KEY (`pages_id`),
|
||||
KEY `data_exact` (`data`),
|
||||
FULLTEXT KEY `data` (`data`)
|
||||
@@ -122,7 +122,7 @@ INSERT INTO `field_title` (`pages_id`, `data`) VALUES (54,'Lock or unlock a page
|
||||
DROP TABLE IF EXISTS `templates`;
|
||||
CREATE TABLE `templates` (
|
||||
`id` int(10) unsigned NOT NULL auto_increment,
|
||||
`name` varchar(255) character set ascii NOT NULL,
|
||||
`name` varchar(250) character set ascii NOT NULL,
|
||||
`fieldgroups_id` int(10) unsigned NOT NULL default '0',
|
||||
`flags` int(11) NOT NULL default '0',
|
||||
`cache_time` mediumint(9) NOT NULL default '0',
|
||||
@@ -141,7 +141,7 @@ DROP TABLE IF EXISTS `fieldgroups`;
|
||||
|
||||
CREATE TABLE `fieldgroups` (
|
||||
`id` int(10) unsigned NOT NULL auto_increment,
|
||||
`name` varchar(255) character set ascii NOT NULL,
|
||||
`name` varchar(250) character set ascii NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=97 DEFAULT CHARSET=utf8;
|
||||
@@ -173,9 +173,9 @@ DROP TABLE IF EXISTS `fields`;
|
||||
CREATE TABLE `fields` (
|
||||
`id` int(10) unsigned NOT NULL auto_increment,
|
||||
`type` varchar(128) character set ascii NOT NULL,
|
||||
`name` varchar(255) character set ascii NOT NULL,
|
||||
`name` varchar(250) character set ascii NOT NULL,
|
||||
`flags` int(11) NOT NULL default '0',
|
||||
`label` varchar(255) NOT NULL default '',
|
||||
`label` varchar(250) NOT NULL default '',
|
||||
`data` text NOT NULL,
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `name` (`name`),
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -305,7 +305,7 @@
|
||||
|
||||
.InputfieldItemList {
|
||||
/* nested item list */
|
||||
.InputfieldItemHeader:not(:hover) {
|
||||
.InputfieldItemHeader:not(:hover):not(.ui-state-error) {
|
||||
/* lighten up nested item list headers use a different color */
|
||||
background: $ui-state-default-bg;
|
||||
color: $ui-state-default-color;
|
||||
|
@@ -113,6 +113,7 @@ var ProcessWireAdminTheme = {
|
||||
// double click occurred
|
||||
clearTimeout(clickTimer);
|
||||
numClicks = 0;
|
||||
window.location.href = $a.attr('href');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
File diff suppressed because one or more lines are too long
@@ -402,7 +402,7 @@ table {
|
||||
//border-color: darken($item-border-color, 4%);
|
||||
background: $item-bg;
|
||||
border: none;
|
||||
margin-bottom: 1em;
|
||||
//margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.InputfieldItemList .InputfieldItemHeader {
|
||||
@@ -440,7 +440,8 @@ table {
|
||||
color: $ui-state-default-color;
|
||||
}
|
||||
|
||||
.InputfieldItemList .InputfieldItemHeader.ui-state-error {
|
||||
.InputfieldItemList .InputfieldItemHeader.ui-state-error,
|
||||
.InputfieldItemList .InputfieldItemList .InputfieldItemHeader.ui-state-error {
|
||||
/* deleted item state */
|
||||
text-decoration: line-through;
|
||||
background: $error-bg;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -38,8 +38,9 @@ class FieldtypeEmail extends FieldtypeText {
|
||||
}
|
||||
|
||||
public function getDatabaseSchema(Field $field) {
|
||||
$len = $this->wire('database')->getMaxIndexLength();
|
||||
$schema = parent::getDatabaseSchema($field);
|
||||
$schema['data'] = "varchar(250) NOT NULL default ''";
|
||||
$schema['data'] = "varchar($len) NOT NULL default ''";
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
@@ -357,8 +357,9 @@ class FieldtypeFile extends FieldtypeMulti {
|
||||
$database = $this->wire('database');
|
||||
$schema = parent::getDatabaseSchema($field);
|
||||
$table = $database->escapeTable($field->table);
|
||||
$maxLen = $database->getMaxIndexLength();
|
||||
|
||||
$schema['data'] = 'varchar(250) NOT NULL';
|
||||
$schema['data'] = "varchar($maxLen) NOT NULL";
|
||||
$schema['description'] = "text NOT NULL";
|
||||
$schema['modified'] = "datetime";
|
||||
$schema['created'] = "datetime";
|
||||
|
@@ -702,6 +702,7 @@ class SelectableOptionManager extends Wire {
|
||||
$database = $this->wire('database');
|
||||
$table = self::optionsTable;
|
||||
$languages = $this->wire('languages');
|
||||
$maxLen = $database->getMaxIndexLength();
|
||||
|
||||
// check for added languages
|
||||
foreach($languages as $language) {
|
||||
@@ -715,13 +716,13 @@ class SelectableOptionManager extends Wire {
|
||||
|
||||
try {
|
||||
$database->exec("ALTER TABLE $table ADD $titleCol TEXT");
|
||||
$database->exec("ALTER TABLE $table ADD UNIQUE $titleCol ($titleCol(250), fields_id)");
|
||||
$database->exec("ALTER TABLE $table ADD UNIQUE $titleCol ($titleCol($maxLen), fields_id)");
|
||||
} catch(\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
}
|
||||
try {
|
||||
$database->exec("ALTER TABLE $table ADD $valueCol VARCHAR(250)");
|
||||
$database->exec("ALTER TABLE $table ADD INDEX $valueCol ($valueCol(250), fields_id)");
|
||||
$database->exec("ALTER TABLE $table ADD $valueCol VARCHAR($maxLen)");
|
||||
$database->exec("ALTER TABLE $table ADD INDEX $valueCol ($valueCol($maxLen), fields_id)");
|
||||
$database->exec("ALTER TABLE $table ADD FULLTEXT {$titleCol}_$valueCol ($titleCol, $valueCol)");
|
||||
} catch(\Exception $e) {
|
||||
$this->error($e->getMessage());
|
||||
@@ -755,6 +756,7 @@ class SelectableOptionManager extends Wire {
|
||||
public function install() {
|
||||
|
||||
$database = $this->wire('database');
|
||||
$maxLen = $database->getMaxIndexLength();
|
||||
$query = $database->prepare("SHOW TABLES LIKE '" . self::optionsTable . "'");
|
||||
$query->execute();
|
||||
|
||||
@@ -766,11 +768,11 @@ class SelectableOptionManager extends Wire {
|
||||
"fields_id INT UNSIGNED NOT NULL, " .
|
||||
"option_id INT UNSIGNED NOT NULL, " .
|
||||
"`title` TEXT, " .
|
||||
"`value` VARCHAR(250), " .
|
||||
"`value` VARCHAR($maxLen), " .
|
||||
"sort INT UNSIGNED NOT NULL, " .
|
||||
"PRIMARY KEY (fields_id, option_id), " .
|
||||
"UNIQUE title (title(250), fields_id), " .
|
||||
"INDEX `value` (`value`(250), fields_id), " .
|
||||
"UNIQUE title (title($maxLen), fields_id), " .
|
||||
"INDEX `value` (`value`($maxLen), fields_id), " .
|
||||
"INDEX sort (sort, fields_id), " .
|
||||
"FULLTEXT title_value (`title`, `value`)" .
|
||||
") ENGINE=$engine DEFAULT CHARSET=$charset";
|
||||
|
@@ -196,6 +196,7 @@ class InputfieldRepeater extends Inputfield implements InputfieldItemList {
|
||||
*/
|
||||
protected function preloadInputfieldAssets($fieldIDs = array()) {
|
||||
if(empty($fieldIDs)) $fieldIDs = $this->field->get('repeaterFields');
|
||||
if(!is_array($fieldIDs)) return;
|
||||
foreach($fieldIDs as $fieldID) {
|
||||
$field = $this->wire('fields')->get($fieldID);
|
||||
try {
|
||||
|
@@ -120,6 +120,8 @@ class InputfieldFile extends Inputfield implements InputfieldItemList {
|
||||
// get the max filesize
|
||||
$filesize = trim(ini_get('post_max_size'));
|
||||
$last = strtolower(substr($filesize, -1));
|
||||
if(ctype_alpha($last)) $filesize = rtrim($filesize, $last);
|
||||
$filesize = (int) $filesize;
|
||||
if($last == 'g') $this->maxFilesize = (($filesize*1024)*1024)*1024;
|
||||
else if($last == 'm') $this->maxFilesize = ($filesize*1024)*1024;
|
||||
else if($last == 'k') $this->maxFilesize = $filesize*1024;
|
||||
|
@@ -1,6 +1,8 @@
|
||||
jQuery(document).ready(function($) {
|
||||
|
||||
$("input.InputfieldPasswordComplexify").each(function() {
|
||||
var $inputs = $("input.InputfieldPasswordComplexify");
|
||||
|
||||
$inputs.each(function() {
|
||||
|
||||
var $input = $(this);
|
||||
var $inputfield = $input.closest('.Inputfield');
|
||||
@@ -146,4 +148,16 @@ jQuery(document).ready(function($) {
|
||||
if($on) $on.addClass('on').siblings('.on').removeClass('on');
|
||||
});
|
||||
});
|
||||
|
||||
// accommodate issue where Firefox auto-populates remembered password when it shouldn't
|
||||
var $ffinputs = $inputs.filter("[autocomplete='off']");
|
||||
if($ffinputs.length) {
|
||||
setTimeout(function() {
|
||||
$ffinputs.each(function() {
|
||||
if($(this).val().length < 1) return;
|
||||
$(this).val('').trigger('keyup').change()
|
||||
.closest('.Inputfield').removeClass('InputfieldStateChanged');
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
});
|
@@ -1 +1 @@
|
||||
jQuery(document).ready(function(a){a("input.InputfieldPasswordComplexify").each(function(){var h=a(this);var b=h.closest(".Inputfield");var g=b.find(".InputfieldPasswordConfirm");var f=g.next(".pass-confirm");var i=h.siblings(".pass-scores");var c=h.siblings(".pass-percent");var j=i.children();var e=i.attr("data-requirements").split(" ");var d=parseInt(h.attr("minlength"));var k={banMode:h.attr("data-banMode"),strengthScaleFactor:parseFloat(h.attr("data-factor"))};h.complexify(k,function(l,m){var s=null;var q=h.val();var t=q.length;var v=0;if(t>0){for(var p=0;p<e.length;p++){var r=false;var x=e[p];var u=b.find(".pass-require-"+x);if(x=="letter"){var w=XRegExp("\\p{L}");if(!w.test(q)){r=true}}else{if(x=="upper"){var w=XRegExp("\\p{Lu}");if(!w.test(q)){r=true}}else{if(x=="lower"){var w=XRegExp("\\p{Ll}");if(!w.test(q)){r=true}}else{if(x=="digit"){var w=XRegExp("\\p{N}");if(!w.test(q)){r=true}}else{if(x=="other"){var w=XRegExp("\\p{P}");var o=XRegExp("\\p{S}");if(!w.test(q)&&!o.test(q)){r=true}}else{if(x=="space"){var w=XRegExp("\\p{Z}");if(!w.test(q)){r=true}}else{if(x=="minlength"){if(t<d){r=true}}}}}}}}if(r){u.removeClass("pass-require-good ui-priority-secondary")}else{u.addClass("pass-require-good ui-priority-secondary");v++}}}else{b.find(".pass-require-good").removeClass("pass-require-good ui-priority-secondary")}if(t==0){j.removeClass("on");return}else{if(v<e.length){s=j.filter(".pass-fail")}else{if(t<d){s=j.filter(".pass-short")}else{if(!l){s=j.filter(".pass-common")}else{if(m==0){s=j.filter(".pass-invalid")}else{if(m<50){s=j.filter(".pass-weak")}else{if(m<70){s=j.filter(".pass-medium")}else{if(m<100){s=j.filter(".pass-good")}else{if(m==100){s=j.filter(".pass-excellent")}}}}}}}}}if(s&&!s.hasClass("on")){s.siblings(".on").removeClass("on");s.addClass("on")}if(s.hasClass("pass-fail")||s.hasClass("pass-short")||s.hasClass("pass-common")||s.hasClass("pass-invalid")){g.attr("disabled","disabled").val("").change()}else{g.removeAttr("disabled");s.find("small").remove();s.append("<small style='margin-left:0.5em'>("+Math.floor(m)+"%)</small>")}if(g.val().length){g.change()}});h.on("change",function(){var l=a(this).val();if(l.length>0){h.attr("required","required");g.attr("required","required")}else{if(!a(this).closest(".InputfieldStateRequired").length){h.removeAttr("required");g.removeAttr("required")}}});g.on("keyup change",function(){var o=h.val();var n=a(this).val();var l=null;var m=h.closest("p").removeClass("pass-matches");if(n.length==0){l=f.children(".confirm-pending")}else{if(o==n){l=f.children(".confirm-yes");m.addClass("pass-matches")}else{if(o.indexOf(n)===0){l=f.children(".confirm-qty");l.children("span").html(n.length+"/"+o.length)}else{l=f.children(".confirm-no")}}}if(l){l.addClass("on").siblings(".on").removeClass("on")}})})});
|
||||
jQuery(document).ready(function(c){var a=c("input.InputfieldPasswordComplexify");a.each(function(){var j=c(this);var d=j.closest(".Inputfield");var i=d.find(".InputfieldPasswordConfirm");var h=i.next(".pass-confirm");var k=j.siblings(".pass-scores");var e=j.siblings(".pass-percent");var l=k.children();var g=k.attr("data-requirements").split(" ");var f=parseInt(j.attr("minlength"));var m={banMode:j.attr("data-banMode"),strengthScaleFactor:parseFloat(j.attr("data-factor"))};j.complexify(m,function(o,p){var u=null;var s=j.val();var v=s.length;var x=0;if(v>0){for(var r=0;r<g.length;r++){var t=false;var z=g[r];var w=d.find(".pass-require-"+z);if(z=="letter"){var y=XRegExp("\\p{L}");if(!y.test(s)){t=true}}else{if(z=="upper"){var y=XRegExp("\\p{Lu}");if(!y.test(s)){t=true}}else{if(z=="lower"){var y=XRegExp("\\p{Ll}");if(!y.test(s)){t=true}}else{if(z=="digit"){var y=XRegExp("\\p{N}");if(!y.test(s)){t=true}}else{if(z=="other"){var y=XRegExp("\\p{P}");var q=XRegExp("\\p{S}");if(!y.test(s)&&!q.test(s)){t=true}}else{if(z=="space"){var y=XRegExp("\\p{Z}");if(!y.test(s)){t=true}}else{if(z=="minlength"){if(v<f){t=true}}}}}}}}if(t){w.removeClass("pass-require-good ui-priority-secondary")}else{w.addClass("pass-require-good ui-priority-secondary");x++}}}else{d.find(".pass-require-good").removeClass("pass-require-good ui-priority-secondary")}if(v==0){l.removeClass("on");return}else{if(x<g.length){u=l.filter(".pass-fail")}else{if(v<f){u=l.filter(".pass-short")}else{if(!o){u=l.filter(".pass-common")}else{if(p==0){u=l.filter(".pass-invalid")}else{if(p<50){u=l.filter(".pass-weak")}else{if(p<70){u=l.filter(".pass-medium")}else{if(p<100){u=l.filter(".pass-good")}else{if(p==100){u=l.filter(".pass-excellent")}}}}}}}}}if(u&&!u.hasClass("on")){u.siblings(".on").removeClass("on");u.addClass("on")}if(u.hasClass("pass-fail")||u.hasClass("pass-short")||u.hasClass("pass-common")||u.hasClass("pass-invalid")){i.attr("disabled","disabled").val("").change()}else{i.removeAttr("disabled");u.find("small").remove();u.append("<small style='margin-left:0.5em'>("+Math.floor(p)+"%)</small>")}if(i.val().length){i.change()}});j.on("change",function(){var n=c(this).val();if(n.length>0){j.attr("required","required");i.attr("required","required")}else{if(!c(this).closest(".InputfieldStateRequired").length){j.removeAttr("required");i.removeAttr("required")}}});i.on("keyup change",function(){var q=j.val();var p=c(this).val();var n=null;var o=j.closest("p").removeClass("pass-matches");if(p.length==0){n=h.children(".confirm-pending")}else{if(q==p){n=h.children(".confirm-yes");o.addClass("pass-matches")}else{if(q.indexOf(p)===0){n=h.children(".confirm-qty");n.children("span").html(p.length+"/"+q.length)}else{n=h.children(".confirm-no")}}}if(n){n.addClass("on").siblings(".on").removeClass("on")}})});var b=a.filter("[autocomplete='off']");if(b.length){setTimeout(function(){b.each(function(){if(c(this).val().length<1){return}c(this).val("").trigger("keyup").change().closest(".Inputfield").removeClass("InputfieldStateChanged")})},1000)}});
|
@@ -2,6 +2,16 @@
|
||||
|
||||
/**
|
||||
* An Inputfield for handling a password
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @property array $requirements Array of requirements (See require* constants)
|
||||
* @property array $requirementsLabels Text labels used for requirements
|
||||
* @property float $complexifyFactor Complexify factor
|
||||
* @property string $complexifyBanMode Complexify ban mode (default='loose')
|
||||
* @property bool $showPass Allow password to be rendered in renderValue and/or re-populated in form?
|
||||
* @property string $defaultLabel Default label for field (default='Set Password'). Used when no 'label' has been set.
|
||||
*
|
||||
*/
|
||||
class InputfieldPassword extends InputfieldText {
|
||||
@@ -14,15 +24,49 @@ class InputfieldPassword extends InputfieldText {
|
||||
'permanent' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Requirements: letter required
|
||||
*
|
||||
*/
|
||||
const requireLetter = 'letter';
|
||||
|
||||
const requireLetter = 'letter';
|
||||
/**
|
||||
* Requirements: lowercase letter required
|
||||
*
|
||||
*/
|
||||
const requireLowerLetter = 'lower';
|
||||
const requireUpperLetter = 'upper';
|
||||
|
||||
/**
|
||||
* Requirements: uppercase letter required
|
||||
*
|
||||
*/
|
||||
const requireUpperLetter = 'upper';
|
||||
|
||||
/**
|
||||
* Requirements: digit required
|
||||
*
|
||||
*/
|
||||
const requireDigit = 'digit';
|
||||
|
||||
/**
|
||||
* Requirements: other character (symbol) required
|
||||
*
|
||||
*/
|
||||
const requireOther = 'other';
|
||||
|
||||
/**
|
||||
* Page being edited, when applicable
|
||||
*
|
||||
* @var User|Page|null
|
||||
*
|
||||
*/
|
||||
protected $_page = null;
|
||||
|
||||
/**
|
||||
* Construct and establish default settings
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
$this->attr('type', 'password');
|
||||
@@ -41,8 +85,11 @@ class InputfieldPassword extends InputfieldText {
|
||||
));
|
||||
$this->set('showPass', false); // allow password to be rendered in renderValue and/or re-populated in form?
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Init Inputfield, establishing the label if none has been set
|
||||
*
|
||||
*/
|
||||
public function init() {
|
||||
parent::init();
|
||||
$this->set('defaultLabel', $this->_('Set Password'));
|
||||
@@ -60,6 +107,15 @@ class InputfieldPassword extends InputfieldText {
|
||||
if($page->hasStatus(Page::statusUnpublished)) $this->required = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before render
|
||||
*
|
||||
* @param Inputfield $parent
|
||||
* @param bool $renderValueMode
|
||||
* @return bool
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
public function renderReady(Inputfield $parent = null, $renderValueMode = false) {
|
||||
if($this->label == 'Set Password') $this->label = $this->defaultLabel;
|
||||
$config = $this->wire('config');
|
||||
@@ -67,9 +123,17 @@ class InputfieldPassword extends InputfieldText {
|
||||
$config->scripts->add($url . 'jquery.complexify.min.js');
|
||||
$config->scripts->add($url . 'jquery.complexify.banlist.js');
|
||||
$this->wire('modules')->get('JqueryCore')->use('xregexp');
|
||||
$page = $this->wire('page');
|
||||
if($page && $page->template == 'admin') $this->attr('autocomplete', 'off'); // ProcessProfile and ProcessUser
|
||||
return parent::renderReady($parent, $renderValueMode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render Password input(s)
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___render() {
|
||||
|
||||
$description = $this->getSetting('description');
|
||||
@@ -109,8 +173,7 @@ class InputfieldPassword extends InputfieldText {
|
||||
$this->attr('data-banMode', $this->complexifyBanMode ? $this->complexifyBanMode : 'loose');
|
||||
$this->attr('data-factor', $this->complexifyFactor ? $this->complexifyFactor : '0.7');
|
||||
$this->addClass('InputfieldPasswordComplexify');
|
||||
$matchYes = $this->_('Matches');
|
||||
$matchNo = $this->_('Does not match');
|
||||
|
||||
$failIcon = "<i class='fa fa-fw fa-frown-o'></i>";
|
||||
$okIcon = "<i class='fa fa-fw fa-meh-o'></i>";
|
||||
$goodIcon = "<i class='fa fa-fw fa-smile-o'></i>";
|
||||
@@ -141,9 +204,18 @@ class InputfieldPassword extends InputfieldText {
|
||||
|
||||
$this->attr('value', $value);
|
||||
if($trackChanges) $this->setTrackChanges(true);
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set Inputfield setting
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
public function set($key, $value) {
|
||||
if($key == 'collapsed' && $this->_page && $this->_page->hasStatus(Page::statusUnpublished)) {
|
||||
// prevent collapse of field when pass is for unpublished user
|
||||
@@ -152,6 +224,12 @@ class InputfieldPassword extends InputfieldText {
|
||||
return parent::set($key, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render non-editable Inputfield
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
*/
|
||||
public function ___renderValue() {
|
||||
if(!$this->getSetting('showPass')) {
|
||||
$value = strlen($this->attr('value')) ? '******' : '';
|
||||
@@ -162,12 +240,20 @@ class InputfieldPassword extends InputfieldText {
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process input
|
||||
*
|
||||
* @param WireInputData $input
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
public function ___processInput(WireInputData $input) {
|
||||
|
||||
parent::___processInput($input);
|
||||
|
||||
$key = $this->attr('name');
|
||||
$value = $this->attr('value');
|
||||
if($value) {}
|
||||
|
||||
if(isset($input->$key)) {
|
||||
// form was submitted
|
||||
@@ -262,6 +348,8 @@ class InputfieldPassword extends InputfieldText {
|
||||
|
||||
/**
|
||||
* Return the fields required to configure an instance of InputfieldPassword
|
||||
*
|
||||
* @return InputfieldWrapper
|
||||
*
|
||||
*/
|
||||
public function ___getConfigInputfields() {
|
||||
|
@@ -10,6 +10,8 @@
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
*
|
||||
* @method upgrade($fromVersion, $toVersion)
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -172,6 +174,7 @@ class PagePathHistory extends WireData implements Module {
|
||||
|
||||
try {
|
||||
$query->execute();
|
||||
/** @noinspection PhpAssignmentInConditionInspection */
|
||||
while($row = $query->fetch(\PDO::FETCH_NUM)) {
|
||||
$paths[] = $this->wire('sanitizer')->pagePathName($row[0], Sanitizer::toUTF8);
|
||||
}
|
||||
@@ -184,10 +187,13 @@ class PagePathHistory extends WireData implements Module {
|
||||
|
||||
/**
|
||||
* Hook called when a page is moved or renamed
|
||||
*
|
||||
* @param HookEvent $event
|
||||
*
|
||||
*/
|
||||
public function hookPageMoved(HookEvent $event) {
|
||||
|
||||
/** @var Page $page */
|
||||
$page = $event->arguments[0];
|
||||
if($page->template == 'admin') return;
|
||||
$age = time() - $page->created;
|
||||
@@ -200,12 +206,13 @@ class PagePathHistory extends WireData implements Module {
|
||||
$parentPrevious = $page->parentPrevious;
|
||||
if($parentPrevious && $parentPrevious->id == $page->parent()->id) $parentPrevious = null;
|
||||
foreach($languages as $language) {
|
||||
/** @var Language $language */
|
||||
if($language->isDefault()) continue;
|
||||
$namePrevious = $page->get("-name$language");
|
||||
if(!$namePrevious && !$parentPrevious) continue;
|
||||
if(!$namePrevious) $namePrevious = $page->name;
|
||||
$languages->setLanguage($language);
|
||||
$pathPrevious = $parentPrevious ? $parentPrevious->path() : $page->parent()->path;
|
||||
$pathPrevious = $parentPrevious ? $parentPrevious->path() : $page->parent()->path();
|
||||
$pathPrevious = rtrim($pathPrevious, '/') . "/$namePrevious";
|
||||
$this->setPathHistory($page, $pathPrevious, $language->id);
|
||||
$languages->unsetLanguage();
|
||||
@@ -243,6 +250,8 @@ class PagePathHistory extends WireData implements Module {
|
||||
|
||||
/**
|
||||
* Hook called upon 404 from ProcessPageView::pageNotFound
|
||||
*
|
||||
* @param HookEvent $event
|
||||
*
|
||||
*/
|
||||
public function hookPageNotFound(HookEvent $event) {
|
||||
@@ -370,6 +379,8 @@ class PagePathHistory extends WireData implements Module {
|
||||
|
||||
/**
|
||||
* When a page is deleted, remove it from our redirects list as well
|
||||
*
|
||||
* @param HookEvent $event
|
||||
*
|
||||
*/
|
||||
public function hookPageDeleted(HookEvent $event) {
|
||||
@@ -380,10 +391,16 @@ class PagePathHistory extends WireData implements Module {
|
||||
$query->execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Install
|
||||
*
|
||||
*/
|
||||
public function ___install() {
|
||||
|
||||
$len = $this->wire('database')->getMaxIndexLength();
|
||||
|
||||
$sql = "CREATE TABLE " . self::dbTableName . " (" .
|
||||
"path VARCHAR(250) NOT NULL, " .
|
||||
"path VARCHAR($len) NOT NULL, " .
|
||||
"pages_id INT UNSIGNED NOT NULL, " .
|
||||
"language_id INT UNSIGNED DEFAULT 0, " . // v2
|
||||
"created TIMESTAMP NOT NULL, " .
|
||||
@@ -396,6 +413,10 @@ class PagePathHistory extends WireData implements Module {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninstall
|
||||
*
|
||||
*/
|
||||
public function ___uninstall() {
|
||||
$this->wire('database')->query("DROP TABLE " . self::dbTableName);
|
||||
}
|
||||
|
@@ -1040,7 +1040,7 @@ class ProcessField extends Process implements ConfigurableModule {
|
||||
//$form->head = $this->_('Basic field settings');
|
||||
$field = $this->modules->get('InputfieldName');
|
||||
$field->attr('value', $this->field->name);
|
||||
$field->description = $this->_("Any combination of ASCII letters [a-z], numbers [0-9], or underscores (no dashes or spaces).");
|
||||
$field->description = $this->_("Use only ASCII letters (a-z A-Z), numbers (0-9) or underscores.");
|
||||
$form->add($field);
|
||||
|
||||
$field = $this->modules->get('InputfieldSelect');
|
||||
|
@@ -1399,7 +1399,9 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
||||
}
|
||||
|
||||
$submitAction = $this->wire('input')->post('_after_submit_action');
|
||||
if($submitAction == 'exit') {
|
||||
if($this->redirectUrl) {
|
||||
// non-default redirectUrl overrides after_submit_action
|
||||
} else if($submitAction == 'exit') {
|
||||
$this->redirectUrl = '../';
|
||||
} else if($submitAction == 'view') {
|
||||
$this->redirectUrl = $this->page->httpUrl();
|
||||
@@ -1791,9 +1793,10 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
||||
*
|
||||
*/
|
||||
public function ___executeTemplate() {
|
||||
|
||||
if(!$this->useSettings || !$this->user->hasPermission('page-template', $this->page))
|
||||
throw new WireException("You don't have permission to change the template on this page.");
|
||||
|
||||
if(!$this->useSettings || !$this->user->hasPermission('page-template', $this->page)) {
|
||||
throw new WireException("You don't have permission to change the template on this page.");
|
||||
}
|
||||
|
||||
if(!isset($_GET['template'])) throw new WireException("This method requires a 'template' get var");
|
||||
$template = $this->templates->get((int) $_GET['template']);
|
||||
@@ -1802,25 +1805,32 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
||||
if(!$this->isAllowedTemplate($template->id)) {
|
||||
throw new WireException("That template is not allowed");
|
||||
}
|
||||
|
||||
$labelConfirm = $this->_('Confirm template change'); // Change template confirmation subhead
|
||||
$labelAction = sprintf($this->_('Change template from "%1$s" to "%2$s"'), $this->page->template, $template); // Change template A to B headline
|
||||
|
||||
$this->headline($labelConfirm);
|
||||
|
||||
/** @var InputfieldForm $form */
|
||||
$form = $this->modules->get("InputfieldForm");
|
||||
$form->attr('action', 'saveTemplate');
|
||||
$form->attr('method', 'post');
|
||||
$form->description = sprintf($this->_('Change template from "%1$s" to "%2$s"'), $this->page->template, $template); // Change template A to B headline
|
||||
$form->description = $labelAction;
|
||||
|
||||
/** @var InputfieldMarkup $f */
|
||||
$f = $this->modules->get("InputfieldMarkup");
|
||||
$f->icon = 'cubes';
|
||||
$f->label = $this->_('Confirm template change'); // Change template confirmation subhead
|
||||
$list = '';
|
||||
$f->label = $labelConfirm;
|
||||
$list = array();
|
||||
foreach($this->page->template->fieldgroup as $field) {
|
||||
if(!$template->fieldgroup->has($field))
|
||||
$list .= "<li class='ui-state-error-text'> <i class='icon-times-circle'></i> $field</li>";
|
||||
if(!$template->fieldgroup->has($field)) {
|
||||
$list[] = $this->wire('sanitizer')->entities($field->getLabel()) . " ($field->name)";
|
||||
}
|
||||
}
|
||||
if(!$list) $this->executeSaveTemplate($template);
|
||||
$f->description = $this->_('Warning, changing the template will delete the following fields:'); // Headline that precedes list of fields that will be deleted as a result of template change
|
||||
$f->attr('value', "<ul>$list</ul>");
|
||||
$icon = "<i class='fa fa-times-circle'></i> ";
|
||||
$f->attr('value', "<p class='ui-state-error-text'>$icon" . implode("<br />$icon", $list) . '</p>');
|
||||
$form->append($f);
|
||||
|
||||
/** @var InputfieldCheckbox $f */
|
||||
@@ -1828,6 +1838,8 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
|
||||
$f->attr('name', 'template');
|
||||
$f->attr('value', $template->id);
|
||||
$f->label = $this->_('Are you sure?'); // Checkbox label to confirm they want to change template
|
||||
$f->label2 = $labelAction;
|
||||
$f->icon = 'warning';
|
||||
$f->description = $this->_('Please confirm that you understand the above by clicking the checkbox below.'); // Checkbox description to confirm they want to change template
|
||||
$form->append($f);
|
||||
|
||||
|
@@ -32,6 +32,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
|
||||
protected $maxImageWidth = 835;
|
||||
protected $page = null;
|
||||
protected $masterPage = null;
|
||||
protected $editorPage = null;
|
||||
protected $defaultClass = 'Pageimage';
|
||||
protected $file = '';
|
||||
@@ -167,7 +168,18 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
if(!$this->page) $this->page = $this->pages->get($id);
|
||||
if(!$this->page) throw new WireException("No page specified");
|
||||
if(!$this->page->id) throw new WireException("Unknown page");
|
||||
if(!$this->editorPage) $this->editorPage = $this->page;
|
||||
if(!$this->editorPage) $this->editorPage = $this->page;
|
||||
|
||||
// if $this->page is a repeater item (for example), $this->masterPage is page it lives on
|
||||
$p = null;
|
||||
if(strpos($this->page->className(), 'Repeater') !== false) {
|
||||
/** @var RepeaterPage $p */
|
||||
$p = $this->page;
|
||||
while(strpos($p->className(), 'Repeater') !== false) {
|
||||
$p = $p->getForPage();
|
||||
}
|
||||
}
|
||||
$this->masterPage = $p && $p->id ? $p : $this->page;
|
||||
|
||||
// note we use hasPermission('page-view') rather than viewable() here because
|
||||
// we want to allow pages without template files
|
||||
@@ -177,14 +189,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
&& $this->wire('modules')->get('PagePermissions')->userFieldEditable($fieldName)) {
|
||||
// user editing allowed images field in their profile
|
||||
} else if(strpos($this->page->className(), 'Repeater') !== false) {
|
||||
/** @var RepeaterPage $p */
|
||||
$p = $this->page;
|
||||
while(strpos($p->className(), 'Repeater') !== false) {
|
||||
$p = $p->getForPage();
|
||||
}
|
||||
if($p && $p->id && $p->editable()) {
|
||||
// okay
|
||||
} else {
|
||||
if(!$this->masterPage->editable()) {
|
||||
throw new WireException($this->labels['noAccess']);
|
||||
}
|
||||
} else {
|
||||
@@ -554,7 +559,7 @@ class ProcessPageEditImageSelect extends Process implements ConfigurableModule {
|
||||
*
|
||||
*/
|
||||
public function checkImageEditPermission($throw = true) {
|
||||
if(!$this->rte && !$this->wire('user')->hasPermission('page-edit-images', $this->page)) {
|
||||
if(!$this->rte && !$this->wire('user')->hasPermission('page-edit-images', $this->masterPage)) {
|
||||
if($throw) {
|
||||
throw new WirePermissionException($this->labels['noAccess']);
|
||||
} else {
|
||||
|
@@ -17,7 +17,7 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
return array(
|
||||
'title' => __('User Profile', __FILE__), // getModuleInfo title
|
||||
'summary' => __('Enables user to change their password, email address and other settings that you define.', __FILE__), // getModuleInfo summary
|
||||
'version' => 102,
|
||||
'version' => 103,
|
||||
'permanent' => true,
|
||||
'permission' => 'profile-edit',
|
||||
);
|
||||
@@ -27,16 +27,23 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
* @var User
|
||||
*
|
||||
*/
|
||||
protected $user;
|
||||
protected $user;
|
||||
|
||||
/**
|
||||
* Construct/establish initial module configuration
|
||||
*
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->set('profileFields', array());
|
||||
}
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute/render profile edit form
|
||||
*
|
||||
* @return string
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
public function ___execute() {
|
||||
|
||||
$fieldName = '';
|
||||
@@ -123,8 +130,11 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
*
|
||||
*/
|
||||
protected function processInput(Inputfield $form, $fieldName = '') {
|
||||
|
||||
/** @var InputfieldForm $form */
|
||||
|
||||
$user = $this->user;
|
||||
$languages = $this->wire('languages');
|
||||
$form->processInput($this->input->post);
|
||||
|
||||
if(count($form->getErrors())) {
|
||||
@@ -141,7 +151,7 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
if($fieldName && $field->name !== $fieldName) continue;
|
||||
|
||||
$field = $this->user->fields->getFieldContext($field);
|
||||
$inputfield = $form->get($field->name);
|
||||
$inputfield = $form->getChildByName($field->name);
|
||||
$value = $inputfield->attr('value');
|
||||
|
||||
if($field->name == 'email' && strlen($value)) {
|
||||
@@ -152,9 +162,20 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
}
|
||||
|
||||
if($field->name == 'pass' && empty($value)) continue;
|
||||
|
||||
if($user->get($field->name) !== $value) {
|
||||
$user->set($field->name, $value);
|
||||
|
||||
if($inputfield->isChanged()) {
|
||||
$v = $user->get($field->name);
|
||||
if($languages && $inputfield->getSetting('useLanguages')) {
|
||||
if(is_object($v)) {
|
||||
$v->setFromInputfield($inputfield);
|
||||
$user->set($field->name, $v);
|
||||
$user->trackChange($field->name);
|
||||
} else {
|
||||
$user->set($field->name, $value);
|
||||
}
|
||||
} else {
|
||||
$user->set($field->name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -171,6 +192,14 @@ class ProcessProfile extends Process implements ConfigurableModule, WirePageEdit
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Module configuration
|
||||
*
|
||||
* @param array $data
|
||||
* @return InputfieldWrapper
|
||||
* @throws WireException
|
||||
*
|
||||
*/
|
||||
public function getModuleConfigInputfields(array $data) {
|
||||
|
||||
$profileFields = isset($data['profileFields']) ? $data['profileFields'] : array();
|
||||
|
@@ -33,17 +33,4 @@ $(document).ready(function() {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// from @horst-n #1236:
|
||||
// prevent browser supported autocomplete for password fields (e.g. on Profilepage)
|
||||
// to force this, attribute autocomplete='off' needs to be set for the password field
|
||||
// this fix is only needed in Mozilla Firefox apparently
|
||||
if($(".FieldtypePassword[autocomplete='off']").length) {
|
||||
// simply set the value empty on document.ready doesn't work in FireFox,
|
||||
// but one second later, it works :)
|
||||
setTimeout(function() {
|
||||
$(".FieldtypePassword[autocomplete='off']").attr('value', '')
|
||||
.closest('.Inputfield').removeClass('InputfieldStateChanged'); // @GerardLuskin
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
|
@@ -1 +1 @@
|
||||
$(document).ready(function(){if($("#Inputfield_id").val()==40){$("#wrap_Inputfield_pass").hide();$("#wrap_Inputfield_email").hide();$("#wrap_Inputfield_roles input").attr("disabled","disabled")}var a=$("#Inputfield_roles_37");if(a.size()>0&&!a.is(":checked")){a.attr("checked","checked")}$("#wrap_Inputfield_roles").find("input[type=checkbox]").each(function(){if($.inArray(parseInt($(this).val()),ProcessWire.config.ProcessUser.editableRoles)==-1){$(this).closest("label").addClass("ui-priority-secondary").click(function(){var b=$(this).find(".ui-state-error-text");if(b.length==0){b=$("<span class='ui-state-error-text'> ("+ProcessWire.config.ProcessUser.notEditableAlert+")</span>");$(this).append(b);setTimeout(function(){b.fadeOut("normal",function(){b.remove()})},2000)}else{b.remove()}return false})}});if($(".FieldtypePassword[autocomplete='off']").length){setTimeout(function(){$(".FieldtypePassword[autocomplete='off']").attr("value","").closest(".Inputfield").removeClass("InputfieldStateChanged")},1000)}});
|
||||
$(document).ready(function(){if($("#Inputfield_id").val()==40){$("#wrap_Inputfield_pass").hide();$("#wrap_Inputfield_email").hide();$("#wrap_Inputfield_roles input").attr("disabled","disabled")}var a=$("#Inputfield_roles_37");if(a.size()>0&&!a.is(":checked")){a.attr("checked","checked")}$("#wrap_Inputfield_roles").find("input[type=checkbox]").each(function(){if($.inArray(parseInt($(this).val()),ProcessWire.config.ProcessUser.editableRoles)==-1){$(this).closest("label").addClass("ui-priority-secondary").click(function(){var b=$(this).find(".ui-state-error-text");if(b.length==0){b=$("<span class='ui-state-error-text'> ("+ProcessWire.config.ProcessUser.notEditableAlert+")</span>");$(this).append(b);setTimeout(function(){b.fadeOut("normal",function(){b.remove()})},2000)}else{b.remove()}return false})}})});
|
Reference in New Issue
Block a user