Skip to content

Commit

Permalink
Various minor updates and optimizations to several core classes
Browse files Browse the repository at this point in the history
  • Loading branch information
ryancramerdesign committed Oct 9, 2019
1 parent 0a01b47 commit 6b20f42
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 21 deletions.
31 changes: 20 additions & 11 deletions wire/core/DatabaseQuerySelectFulltext.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* This file is licensed under the MIT license
* https://processwire.com/about/license/mit/
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
* https://processwire.com
*
*
Expand Down Expand Up @@ -109,11 +109,12 @@ public function match($tableName, $fieldName, $operator, $value) {
break;

case '~=':
case '!~=':
$words = preg_split('/[-\s,]/', $value, -1, PREG_SPLIT_NO_EMPTY);
foreach($words as $word) {
$len = function_exists('mb_strlen') ? mb_strlen($word) : strlen($word);
if(DatabaseStopwords::has($word) || $len < $database->getVariable('ft_min_word_len')) {
$this->matchWordLIKE($tableName, $fieldName, $word);
$this->matchWordLIKE($tableName, $fieldName, $operator, $word);
} else {
$this->matchContains($tableName, $fieldName, $operator, $word);
}
Expand Down Expand Up @@ -192,26 +193,32 @@ protected function matchContains($tableName, $fieldName, $operator, $value) {
$tableField = "$tableName.$fieldName";
$database = $this->wire('database');
$v = $database->escapeStr($value);
$not = strpos($operator, '!') === 0;
if($not) $operator = ltrim($operator, '!');

$n = 0;
do {
$scoreField = "_score_{$tableName}_{$fieldName}" . (++$n);
} while(in_array($scoreField, self::$scoreFields));
self::$scoreFields[] = $scoreField;

$query->select("MATCH($tableField) AGAINST('$v') AS $scoreField");

$match = $not ? 'NOT MATCH' : 'MATCH';
$query->select("$match($tableField) AGAINST('$v') AS $scoreField");
$query->orderby($scoreField . " DESC");

$partial = $operator != '~=';
$partial = $operator != '~=' && $operator != '!~=';
$booleanValue = $database->escapeStr($this->getBooleanQueryValue($value, true, $partial));
if($booleanValue) $j = "MATCH($tableField) AGAINST('$booleanValue' IN BOOLEAN MODE) ";
else $j = '';
if($booleanValue) {
$j = "$match($tableField) AGAINST('$booleanValue' IN BOOLEAN MODE) ";
} else {
$j = '';
}

if($operator == '^=' || $operator == '$=' || ($operator == '*=' && (!$j || preg_match('/[-\s]/', $v)))) {
// if $operator is a ^begin/$end, or if there are any word separators in a *= operator value

if($operator == '^=' || $operator == '$=') {
$type = 'RLIKE';
$type = $not ? 'NOT RLIKE' : 'RLIKE';
$v = $database->escapeStr(preg_quote($value)); // note $value not $v
$like = "[[:space:]]*(<[^>]+>)*[[:space:]]*";
if($operator == '^=') {
Expand All @@ -221,7 +228,7 @@ protected function matchContains($tableName, $fieldName, $operator, $value) {
}

} else {
$type = 'LIKE';
$type = $not ? 'NOT LIKE' : 'LIKE';
$v = $this->escapeLIKE($v);
$like = "%$v%";
}
Expand All @@ -241,15 +248,17 @@ protected function matchContains($tableName, $fieldName, $operator, $value) {
*
* @param string $tableName
* @param string $fieldName
* @param string $operator
* @param $word
*
*/
protected function matchWordLIKE($tableName, $fieldName, $word) {
protected function matchWordLIKE($tableName, $fieldName, $operator, $word) {
$tableField = "$tableName.$fieldName";
$database = $this->wire('database');
$v = $database->escapeStr(preg_quote($word));
$regex = "([[[:blank:][:punct:]]|^)$v([[:blank:][:punct:]]|$)";
$where = "($tableField REGEXP '$regex')";
$type = strpos($operator, '!') === 0 ? 'NOT REGEXP' : 'REGEXP';
$where = "($tableField $type '$regex')";
$this->query->where($where);
}

Expand Down
2 changes: 1 addition & 1 deletion wire/core/Field.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
* @property string $table Database table used by the field #pw-group-properties
* @property string $prevTable Previously database table (if field was renamed) #pw-group-properties
* @property Fieldtype|null $type Fieldtype module that represents the type of this field #pw-group-properties
* @property Fieldtype $prevFieldtype Previous Fieldtype, of type was changed #pw-group-properties
* @property Fieldtype|null $prevFieldtype Previous Fieldtype, if type was changed #pw-group-properties
* @property int $flags Bitmask of flags used by this field #pw-group-properties
* @property-read string $flagsStr Names of flags used by this field (readonly) #pw-group-properties
* @property string $label Text string representing the label of the field #pw-group-properties
Expand Down
2 changes: 1 addition & 1 deletion wire/core/Fieldgroup.php
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,7 @@ public function getPageInputfields(Page $page, $contextStr = '', $fieldName = ''
if(!$inputfield) continue;
if($inputfield->collapsed == Inputfield::collapsedHidden) continue;

$inputfield->setAttribute('value', $page->get($field->name));
if(!$page instanceof NullPage) $inputfield->setAttribute('value', $page->get($field->name));

if($multiMode) {
$fieldInputfields[$field->id] = $inputfield;
Expand Down
11 changes: 8 additions & 3 deletions wire/core/Fieldgroups.php
Original file line number Diff line number Diff line change
Expand Up @@ -467,9 +467,14 @@ public function isFieldNotRemoveable(Field $field, Fieldgroup $fieldgroup, Templ
if(is_null($template)) $template = $this->wire('templates')->get($fieldgroup->name);

if(($field->flags & Field::flagGlobal) && (!$template || !$template->noGlobal)) {
return
"Field '$field' may not be removed from fieldgroup '$fieldgroup->name' " .
"because it is globally required (Field::flagGlobal).";
if($template && $template->getConnectedField()) {
// if template has a 1-1 relationship with a field, noGlobal is not enforced
return false;
} else {
return
"Field '$field' may not be removed from fieldgroup '$fieldgroup->name' " .
"because it is globally required (Field::flagGlobal).";
}
}

if($field->flags & Field::flagPermanent) {
Expand Down
44 changes: 42 additions & 2 deletions wire/core/Template.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* #pw-body Template objects also maintain several properties which can affect the render behavior of pages using it.
* #pw-order-groups identification,manipulation,family,URLs,access,files,cache,page-editor,behaviors,other
*
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
* ProcessWire 3.x, Copyright 2019 by Ryan Cramer
* https://processwire.com
*
* @todo add multi-language option for redirectLogin setting
Expand Down Expand Up @@ -108,6 +108,11 @@
* @property string $tags Optional tags that can group this template with others in the admin templates list. #pw-group-other
* @property string $pageLabelField CSV or space separated string of field names to be displayed by ProcessPageList (overrides those set with ProcessPageList config). #pw-group-other
* @property int|bool $_importMode Internal use property set by template importer when importing #pw-internal
* @property int|null $connectedFieldID ID of connected field or null or 0 if not applicable. #pw-internal
*
* Hookable methods
*
* @method Field|null getConnectedField() Get Field object connected to this field, or null if not applicable. #pw-internal
*
*
*/
Expand Down Expand Up @@ -263,6 +268,7 @@ class Template extends WireData implements Saveable, Exportable {
'nameLabel' => '', // label for the "name" property of the page (if something other than "Name")
'contentType' => '', // Content-type header or index of header from $config->contentTypes
'errorAction' => 0, // action to take on save when required field on published page is empty (0=notify,1=restore,2=unpublish)
'connectedFieldID' => null, // ID of connected field or null if not applicable
'ns' => '', // namespace found in the template file, or blank if not determined
);

Expand Down Expand Up @@ -700,7 +706,10 @@ public function set($key, $value) {
$this->setIcon($value);

} else if($key == 'urlSegments') {
$this->urlSegments($value);
$this->urlSegments($value);

} else if($key == 'connectedFieldID') {
parent::set($key, (int) $value);

} else {
parent::set($key, $value);
Expand Down Expand Up @@ -1192,6 +1201,37 @@ public function setIcon($icon) {
return $this;
}

/**
* Get Field object connected with this template
*
* #pw-internal
*
* @return Field|null Returns Field object or null if not applicable
* @since 3.0.142
*
*/
public function ___getConnectedField() {
if($this->connectedFieldID) {
$field = $this->wire('fields')->get((int) $this->connectedFieldID);
} else {
$field = null;
}
if(!$field) {
$fieldName = '';
$templateName = $this->name;
$prefixes = array('field-', 'field_', 'repeater_');
foreach($prefixes as $prefix) {
if(strpos($templateName, $prefix) !== 0) continue;
list(,$fieldName) = explode($prefix, $templateName, 2);
break;
}
if($fieldName) {
$field = $this->wire('fields')->get($fieldName);
}
}
return $field;
}

/**
* Ensures that isset() and empty() work for this classes properties.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2724,7 +2724,7 @@ class ProcessTemplate extends Process {
}

if($isDeleted) {
if(($field->flags & Field::flagGlobal) && !$this->template->noGlobal) {
if(!$this->template->getConnectedField() && (($field->flags & Field::flagGlobal) && !$this->template->noGlobal)) {
$this->error(sprintf($this->_('Field "%s" may not be removed because it is globally required by all fieldgroups'), $field));
} else {
$removedFields->add($field);
Expand Down
6 changes: 5 additions & 1 deletion wire/templates-admin/scripts/inputfields.js
Original file line number Diff line number Diff line change
Expand Up @@ -848,7 +848,11 @@ function InputfieldColumnWidths($target) {
}

colspacing = $form.attr('data-colspacing');
if(typeof colspacing == 'undefined') colspacing = 1;
if(typeof colspacing == 'undefined') {
colspacing = 1;
} else {
colspacing = parseInt(colspacing);
}

// if no borders, we don't worry about keeping heights aligned since they won't be seen
useHeights = $form.hasClass('InputfieldFormNoHeights') ? false : true;
Expand Down
2 changes: 1 addition & 1 deletion wire/templates-admin/scripts/inputfields.min.js

Large diffs are not rendered by default.

0 comments on commit 6b20f42

Please sign in to comment.