1
0
mirror of https://github.com/processwire/processwire.git synced 2025-08-26 16:14:35 +02:00

7 Commits

14 changed files with 141 additions and 40 deletions

View File

@@ -94,6 +94,10 @@ DirectoryIndex index.php index.html index.htm
# RewriteCond %{HTTPS} off # RewriteCond %{HTTPS} off
# RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301] # RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# If using an AWS load balancer, use these two lines below instead of those above:
# RewriteCond %{HTTP:X-Forwarded-Proto} =http
# RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# ----------------------------------------------------------------------------------------------- # -----------------------------------------------------------------------------------------------
# 10. Set an environment variable so the installer can detect that mod_rewrite is active. # 10. Set an environment variable so the installer can detect that mod_rewrite is active.
# Note that some web hosts don't support this. If you get a 500 error, you might try # Note that some web hosts don't support this. If you get a 500 error, you might try

View File

@@ -763,7 +763,7 @@ class Pagefile extends WireData {
* *
*/ */
public function __toString() { public function __toString() {
return $this->basename; return (string) $this->basename;
} }
/** /**

View File

@@ -45,7 +45,7 @@ class ProcessWire extends Wire {
* Reversion revision number * Reversion revision number
* *
*/ */
const versionRevision = 61; const versionRevision = 62;
/** /**
* Version suffix string (when applicable) * Version suffix string (when applicable)
@@ -258,7 +258,7 @@ class ProcessWire extends Wire {
} }
$config->ajax = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'); $config->ajax = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');
$config->cli = (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || ($_SERVER['argc'] > 0 && is_numeric($_SERVER['argc'])))); $config->cli = (!isset($_SERVER['SERVER_SOFTWARE']) && (php_sapi_name() == 'cli' || (isset($_SERVER['argc']) && $_SERVER['argc'] > 0 && is_numeric($_SERVER['argc']))));
$config->modal = empty($_GET['modal']) ? false : abs((int) $_GET['modal']); $config->modal = empty($_GET['modal']) ? false : abs((int) $_GET['modal']);
$version = self::versionMajor . "." . self::versionMinor . "." . self::versionRevision; $version = self::versionMajor . "." . self::versionMinor . "." . self::versionRevision;

View File

@@ -191,6 +191,14 @@ class WireHttp extends Wire {
*/ */
protected $responseHeaders = array(); protected $responseHeaders = array();
/**
* Last response headers parsed into key => value properties, where value is always array
*
* Note that keys are always lowercase
*
*/
protected $responseHeaderArrays = array();
/** /**
* Error messages * Error messages
* *
@@ -821,10 +829,16 @@ class WireHttp extends Wire {
* Get the last HTTP response headers (associative array) * Get the last HTTP response headers (associative array)
* *
* All headers are translated to `[key => value]` properties in the array. * All headers are translated to `[key => value]` properties in the array.
* The keys are always lowercase. * The keys are always lowercase and the values are always strings. If you
* need multi-value headers, use the `WireHttp::getResponseHeaderValues()` method
* instead, which returns multi-value headers as arrays.
*
* This method always returns an associative array of strings, unless you specify the
* `$key` option in which case it will return a string, or NULL if the header is not present.
* *
* @param string $key Optional header name you want to get (if you only need one) * @param string $key Optional header name you want to get (if you only need one)
* @return array|string|null * @return array|string|null
* @see WireHttp::getResponseHeaderValues()
* *
*/ */
public function getResponseHeaders($key = '') { public function getResponseHeaders($key = '') {
@@ -835,6 +849,37 @@ class WireHttp extends Wire {
return $this->responseHeaders; return $this->responseHeaders;
} }
/**
* Get last HTTP response headers with multi-value headers as arrays
*
* Use this method when you want to retrieve headers that can potentially contain multiple-values.
* Note that any code that iterates these values should be able to handle them being either a string or
* an array.
*
* This method always returns an associative array of strings and arrays, unless you specify the
* `$key` option in which case it can return an array, string, or NULL if the header is not present.
*
* @param string $key Optional header name you want to get (if you only need a specific header)
* @param bool $forceArrays If even single-value headers should be arrays, specify true (default=false).
* @return array|string|null
*
*/
public function getResponseHeaderValues($key = '', $forceArrays = false) {
if(!empty($key)) {
$key = strtolower($key);
$value = isset($this->responseHeaderArrays[$key]) ? $this->responseHeaderArrays[$key] : null;
if(!$value !== null && count($value) === 1 && !$forceArrays) $value = reset($value);
} else if($forceArrays) {
$value = $this->responseHeaderArrays;
} else {
$value = $this->responseHeaders;
foreach($this->responseHeaderArrays as $k => $v) {
if(count($v) > 1) $value[$k] = $v;
}
}
return $value;
}
/** /**
* Set the response header * Set the response header
* *
@@ -847,6 +892,7 @@ class WireHttp extends Wire {
if(!empty($responseHeader[0])) { if(!empty($responseHeader[0])) {
list($http, $httpCode, $httpText) = explode(' ', trim($responseHeader[0]), 3); list($http, $httpCode, $httpText) = explode(' ', trim($responseHeader[0]), 3);
if($http) {} // ignore
$httpCode = (int) $httpCode; $httpCode = (int) $httpCode;
$httpText = preg_replace('/[^-_.;() a-zA-Z0-9]/', ' ', $httpText); $httpText = preg_replace('/[^-_.;() a-zA-Z0-9]/', ' ', $httpText);
} else { } else {
@@ -861,6 +907,8 @@ class WireHttp extends Wire {
// parsed version // parsed version
$this->responseHeaders = array(); $this->responseHeaders = array();
$this->responseHeaderArrays = array();
foreach($responseHeader as $header) { foreach($responseHeader as $header) {
$pos = strpos($header, ':'); $pos = strpos($header, ':');
if($pos !== false) { if($pos !== false) {
@@ -870,7 +918,12 @@ class WireHttp extends Wire {
$key = $header; $key = $header;
$value = ''; $value = '';
} }
if(!isset($this->responseHeaders[$key])) $this->responseHeaders[$key] = $value; if(!isset($this->responseHeaders[$key])) {
$this->responseHeaders[$key] = $value;
$this->responseHeaderArrays[$key] = array($value);
} else {
$this->responseHeaderArrays[$key][] = $value;
}
} }
/* /*

View File

@@ -553,9 +553,22 @@ class FieldtypeRepeater extends Fieldtype implements ConfigurableModule {
$readyPage->save(); $readyPage->save();
} }
$readyPage->setQuietly('_repeater_new', 1); $readyPage->setQuietly('_repeater_new', 1);
$this->readyPageSaved($readyPage, $page, $field);
return $readyPage; return $readyPage;
} }
/**
* Hook called when a ready page is saved
*
* @param Page $readyPage
* @param Page $ownerPage
* @param Field $field
*
*/
protected function ___readyPageSaved(Page $readyPage, Page $ownerPage, Field $field) {
// for hooks only
}
/** /**
* Returns a blank page ready for use as a repeater * Returns a blank page ready for use as a repeater
* *

View File

@@ -223,6 +223,7 @@ function InputfieldRepeater($) {
var $inputfields = $loaded.closest('.Inputfields'); var $inputfields = $loaded.closest('.Inputfields');
if($repeater.hasClass('InputfieldRenderValueMode')) ajaxURL += '&inrvm=1'; if($repeater.hasClass('InputfieldRenderValueMode')) ajaxURL += '&inrvm=1';
if($repeater.hasClass('InputfieldNoDraft')) ajaxURL += '&nodraft=1';
$spinner.removeClass('fa-arrows').addClass('fa-spin fa-spinner'); $spinner.removeClass('fa-arrows').addClass('fa-spin fa-spinner');
repeaterID = repeaterID.replace(/_repeater\d+$/, ''); repeaterID = repeaterID.replace(/_repeater\d+$/, '');

File diff suppressed because one or more lines are too long

View File

@@ -109,7 +109,7 @@ class InputfieldAsmSelect extends InputfieldSelectMultiple implements Inputfield
public function ___getConfigInputfields() { public function ___getConfigInputfields() {
$inputfields = parent::___getConfigInputfields(); $inputfields = parent::___getConfigInputfields();
if($this->hasFieldtype != 'FieldtypePage') return $inputfields; if($this->hasFieldtype != 'FieldtypePage' || !$this->hasField) return $inputfields;
$f = $this->wire('modules')->get('InputfieldRadios'); $f = $this->wire('modules')->get('InputfieldRadios');
$f->attr('name', 'usePageEdit'); $f->attr('name', 'usePageEdit');
$f->label = $this->_('Link selected pages to page editor?'); $f->label = $this->_('Link selected pages to page editor?');

View File

@@ -114,7 +114,7 @@ $(document).ready(function() {
$(document).on('change', '.InputfieldFileUpload input[type=file]', function() { $(document).on('change', '.InputfieldFileUpload input[type=file]', function() {
var $t = $(this); var $t = $(this);
var $mask = $t.parent(".InputMask"); var $mask = $t.closest(".InputMask");
if($t.val().length > 1) { if($t.val().length > 1) {
$mask.addClass("ui-state-disabled"); $mask.addClass("ui-state-disabled");
@@ -130,18 +130,22 @@ $(document).ready(function() {
var maxFiles = parseInt($upload.find('.InputfieldFileMaxFiles').val()); var maxFiles = parseInt($upload.find('.InputfieldFileMaxFiles').val());
var numFiles = $list.children('li').length + $upload.find('input[type=file]').length + 1; var numFiles = $list.children('li').length + $upload.find('input[type=file]').length + 1;
if(maxFiles > 0 && numFiles >= maxFiles) return; if(maxFiles > 0 && numFiles >= maxFiles) {
// no more files allowed
} else {
$upload.find(".InputMask").not(":last").each(function() { $upload.find(".InputMask").not(":last").each(function() {
var $m = $(this); var $m = $(this);
if($m.find("input[type=file]").val() < 1) $m.remove(); if($m.find("input[type=file]").val() < 1) $m.remove();
}); });
// add another input // add another input
var $i = $mask.clone().removeClass("ui-state-disabled"); var $mask2 = $mask.clone().removeClass("ui-state-disabled");
$i.children("input[type=file]").val(''); var $input = $mask2.find('input[type=file]');
$i.insertAfter($mask); $input.attr('id', $input.attr('id') + '-');
$i.css('margin-left', '0.5em').removeClass('ui-state-active'); $input.val('');
$mask2.insertAfter($mask);
$mask2.css('margin-left', '0.5em').removeClass('ui-state-active');
}
// update file input to contain file name // update file input to contain file name
var name = $t.val(); var name = $t.val();

File diff suppressed because one or more lines are too long

View File

@@ -136,17 +136,7 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
|| $this->wire('input')->get('reloadInputfieldAjax') || $this->wire('input')->get('reloadInputfieldAjax')
|| $this->wire('input')->get('renderInputfieldAjax'); || $this->wire('input')->get('renderInputfieldAjax');
// get the max filesize $this->setMaxFilesize(trim(ini_get('post_max_size')));
$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;
else if((int) $filesize > 0) $this->maxFilesize = (int) $filesize;
else $this->maxFilesize = (5*1024)*1024;
$this->uploadOnlyMode = (int) $this->wire('input')->get('uploadOnlyMode'); $this->uploadOnlyMode = (int) $this->wire('input')->get('uploadOnlyMode');
$this->addClass('InputfieldItemList', 'wrapClass'); $this->addClass('InputfieldItemList', 'wrapClass');
$this->addClass('InputfieldHasFileList', 'wrapClass'); $this->addClass('InputfieldHasFileList', 'wrapClass');
@@ -167,6 +157,41 @@ class InputfieldFile extends Inputfield implements InputfieldItemList, Inputfiel
return parent::get($key); return parent::get($key);
} }
public function set($key, $value) {
if($key == 'maxFilesize') return $this->setMaxFilesize($value);
return parent::set($key, $value);
}
/**
* Set the max file size in bytes or use string like "30m", "2g" "500k"
*
* @param int|string $filesize
* @return $this
*
*/
public function setMaxFilesize($filesize) {
if(ctype_digit("$filesize")) {
$this->maxFilesize = (int) $filesize;
} else {
$filesize = rtrim($filesize, 'bB'); // convert mb=>m, gb=>g, kb=>k
$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;
} else if($filesize > 0) {
$this->maxFilesize = $filesize;
} else {
$this->maxFilesize = (5 * 1024) * 1024;
}
}
return $this;
}
/** /**
* Per Inputfield interface, returns true when this field is empty * Per Inputfield interface, returns true when this field is empty
* *

View File

@@ -49,7 +49,7 @@ var InputfieldSelector = {
var $t = $(this); var $t = $(this);
clearTimeout(timeout); clearTimeout(timeout);
if($t.hasClass("input-value-subselect") && InputfieldSelector.valueHasOperator($t.val())) { if($t.hasClass("input-value-subselect") && InputfieldSelector.valueHasOperator($t.val())) {
var $preview = $t.parents('.selector-list').siblings('.selector-preview'); var $preview = $t.closest('.InputfieldContent').find('.selector-preview');
$preview.html('Subselect detected: when done <a href="#" onclick="return false">click here to commit your change</a>.'); $preview.html('Subselect detected: when done <a href="#" onclick="return false">click here to commit your change</a>.');
return; return;
} }
@@ -566,13 +566,13 @@ var InputfieldSelector = {
if(si === null || typeof si == "undefined" || typeof si.value == "undefined") continue; if(si === null || typeof si == "undefined" || typeof si.value == "undefined") continue;
if(si.field == '_custom' && si.isOrGroup) { if(si.field == '_custom' && si.isOrGroup) {
s.isOrGroup = true; s.isOrGroup = true;
} else if(si.mayOrField && si.value == s.value) { } else if(si.mayOrField && si.value == s.value && si.operator == s.operator) {
si.checkbox.show(); si.checkbox.show();
if(si.useOrField) { if(si.useOrField) {
s.field += '|' + si.field; s.field += '|' + si.field;
selectors[i] = null; selectors[i] = null;
} }
} else if(si.mayOrValue && si.field == s.field) { } else if(si.mayOrValue && si.field == s.field && si.operator == s.operator) {
si.checkbox.show(); si.checkbox.show();
if(si.useOrValue) { if(si.useOrValue) {
s.value += '|' + si.value; s.value += '|' + si.value;
@@ -600,7 +600,7 @@ var InputfieldSelector = {
} }
} }
var $preview = $item.parents('.selector-list').siblings('.selector-preview'); var $preview = $item.closest('.InputfieldContent').find('.selector-preview');
var initValue = $preview.attr('data-init-value'); var initValue = $preview.attr('data-init-value');
if(initValue && initValue.length) initValue += ', '; if(initValue && initValue.length) initValue += ', ';

File diff suppressed because one or more lines are too long

View File

@@ -1447,11 +1447,12 @@ class ProcessPageEdit extends Process implements WirePageEditor, ConfigurableMod
* *
*/ */
protected function ___processSaveRedirect($redirectUrl) { protected function ___processSaveRedirect($redirectUrl) {
$admin = true;
if($redirectUrl) { if($redirectUrl) {
$admin = strpos($redirectUrl, $this->wire('config')->urls->admin) === 0; $c = substr($redirectUrl, 0, 1);
$admin = $c === '.' || $c === '?' || strpos($redirectUrl, $this->wire('config')->urls->admin) === 0;
if($admin) $redirectUrl .= (strpos($redirectUrl, '?') === false ? '?' : '&') . 's=1'; if($admin) $redirectUrl .= (strpos($redirectUrl, '?') === false ? '?' : '&') . 's=1';
} else { } else {
$admin = true;
$redirectUrl = "./?id={$this->page->id}&s=1"; $redirectUrl = "./?id={$this->page->id}&s=1";
} }
if($admin) $redirectUrl .= "&c=" . count($this->changes); if($admin) $redirectUrl .= "&c=" . count($this->changes);