mirror of
https://github.com/processwire/processwire.git
synced 2025-08-07 15:26:54 +02:00
Various minor updates. Plus add a $database->isStopword() method and improve error logging in WireDatabasePDOStatement
This commit is contained in:
@@ -120,8 +120,7 @@ abstract class DatabaseQuery extends WireData {
|
||||
* Get or set a bind option
|
||||
*
|
||||
* @param string|bool $optionName One of 'prefix' or 'global', boolean true to get/set all
|
||||
* @param null|int|string|array $optionValue Omit when getting, Specify option value to set, or array when setting
|
||||
* all
|
||||
* @param null|int|string|array $optionValue Omit when getting, Specify option value to set, or array when setting all
|
||||
* @return string|int|array
|
||||
* @since 3.0.157
|
||||
*
|
||||
|
@@ -3,7 +3,7 @@
|
||||
/**
|
||||
* ProcessWire DatabaseStopwords
|
||||
*
|
||||
* MySQL stopwords, primarily for use with filtering fulltext queries
|
||||
* MySQL stopwords, primarily for use with filtering fulltext queries (MyISAM only)
|
||||
*
|
||||
* ProcessWire 3.x, Copyright 2016 by Ryan Cramer
|
||||
* https://processwire.com
|
||||
@@ -49,8 +49,8 @@ class DatabaseStopwords {
|
||||
"various", "very", "via", "viz", "vs", "want", "wants", "was", "wasn't", "way", "we", "we'd", "we'll", "we're", "we've", "welcome", "well", "went", "were",
|
||||
"weren't", "what", "what's", "whatever", "when", "whence", "whenever", "where", "where's", "whereafter", "whereas", "whereby", "wherein", "whereupon",
|
||||
"wherever", "whether", "which", "while", "whither", "who", "who's", "whoever", "whole", "whom", "whose", "why", "will", "willing", "wish", "with", "within",
|
||||
"without", "won't", "wonder", "would", "would", "wouldn't", "yes", "yet", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself",
|
||||
"yourselves", "zero");
|
||||
"without", "won't", "wonder", "would", "wouldn't", "yes", "yet", "you", "you'd", "you'll", "you're", "you've", "your", "yours", "yourself", "yourselves", "zero"
|
||||
);
|
||||
|
||||
/**
|
||||
* Get all stopwords
|
||||
|
@@ -711,9 +711,7 @@ abstract class Fieldtype extends WireData implements Module {
|
||||
|
||||
$table = $database->escapeTable($table);
|
||||
$subfield = $database->escapeCol($subfield);
|
||||
$quoteValue = $database->quote($value);
|
||||
|
||||
$query->where("{$table}.{$subfield}{$operator}$quoteValue"); // QA
|
||||
$query->where("{$table}.{$subfield}{$operator}?", $value); // QA
|
||||
return $query;
|
||||
}
|
||||
|
||||
|
@@ -99,6 +99,7 @@
|
||||
* @property Page|null $_cloning Internal runtime use, contains Page being cloned (source), when this Page is the new copy (target). #pw-internal
|
||||
* @property bool|null $_hasAutogenName Internal runtime use, set by Pages class when page as auto-generated name. #pw-internal
|
||||
* @property bool|null $_forceSaveParents Internal runtime/debugging use, force a page to refresh its pages_parents DB entries on save(). #pw-internal
|
||||
* @property float|null $_pfscore Internal PageFinder fulltext match score when page found/loaded from relevant query. #pw-internal
|
||||
*
|
||||
* Methods added by PageRender.module:
|
||||
* -----------------------------------
|
||||
|
@@ -639,7 +639,7 @@ class PageFinder extends Wire {
|
||||
$score += $v;
|
||||
unset($row[$k]);
|
||||
}
|
||||
$row['score'] = $score; // @todo do we need this anymore?
|
||||
$row['score'] = $score;
|
||||
$matches[] = $row;
|
||||
|
||||
} else if($options['returnAllCols']) {
|
||||
@@ -2298,7 +2298,9 @@ class PageFinder extends Wire {
|
||||
// the following fields are defined in each iteration here because they may be modified in the loop
|
||||
$table = "pages";
|
||||
$operator = $selector->operator;
|
||||
$isPartialOperator = in_array($operator, array('%=', '^=', '$=', '%^=', '%$=', '*='));
|
||||
$compareType = $selectors::getSelectorByOperator($operator, 'compareType');
|
||||
$isPartialOperator = ($compareType & Selector::compareTypeFind);
|
||||
|
||||
$subfield = '';
|
||||
$IDs = array(); // populated in special cases where we can just match parent IDs
|
||||
$sql = '';
|
||||
@@ -3054,7 +3056,10 @@ class PageFinder extends Wire {
|
||||
|
||||
/** @var PageFinder $finder */
|
||||
$finder = $this->wire(new PageFinder());
|
||||
$ids = $finder->findIDs($ownerSelectors);
|
||||
$ids = array();
|
||||
foreach($finder->findIDs($ownerSelectors) as $id) {
|
||||
$ids[] = (int) $id;
|
||||
}
|
||||
|
||||
if($this->isRepeaterFieldtype($ownerField->type)) {
|
||||
// Repeater
|
||||
|
@@ -346,7 +346,7 @@ class PagesLoader extends Wire {
|
||||
// [ pageID => [ all pages columns ] ]
|
||||
$pagesInfo = $pageFinder->findVerboseIDs($selectors, $options);
|
||||
} else {
|
||||
// [ [ 'id' => 3, 'templates_id' => 2, 'parent_id' => 1 ]
|
||||
// [ [ 'id' => 3, 'templates_id' => 2, 'parent_id' => 1, 'score' => 1.123 ]
|
||||
$pagesInfo = $pageFinder->find($selectors, $options);
|
||||
}
|
||||
|
||||
@@ -398,13 +398,16 @@ class PagesLoader extends Wire {
|
||||
$parent_id = $pageFinder->getParentID();
|
||||
$idsSorted = array();
|
||||
$idsByTemplate = array();
|
||||
$scores = array();
|
||||
|
||||
// organize the pages by template ID
|
||||
foreach($pagesInfo as $page) {
|
||||
$tpl_id = $page['templates_id'];
|
||||
$tpl_id = (int) $page['templates_id'];
|
||||
$id = (int) $page['id'];
|
||||
if(!isset($idsByTemplate[$tpl_id])) $idsByTemplate[$tpl_id] = array();
|
||||
$idsByTemplate[$tpl_id][] = $page['id'];
|
||||
$idsSorted[] = $page['id'];
|
||||
$idsByTemplate[$tpl_id][] = $id;
|
||||
$idsSorted[] = $id;
|
||||
if(!empty($page['score'])) $scores[$id] = (float) $page['score'];
|
||||
}
|
||||
|
||||
if(count($idsByTemplate) > 1) {
|
||||
@@ -440,6 +443,12 @@ class PagesLoader extends Wire {
|
||||
|
||||
$sortsAfter = $pageFinder->getSortsAfter();
|
||||
if(count($sortsAfter)) $pages->sort($sortsAfter);
|
||||
|
||||
if(count($scores)) {
|
||||
foreach($pages as $page) {
|
||||
if(isset($scores[$page->id])) $page->setQuietly('_pfscore', $scores[$page->id]);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
$pages = $this->pages->newPageArray($loadOptions);
|
||||
|
@@ -495,7 +495,9 @@ class ProcessWire extends Wire {
|
||||
|
||||
/** @var WireCache $cache */
|
||||
$cache = $this->wire('cache', new WireCache(), true);
|
||||
$cache->preload($config->preloadCacheNames);
|
||||
$cacheNames = $config->preloadCacheNames;
|
||||
if($database->getEngine() === 'innodb') $cacheNames[] = 'InnoDB.stopwords';
|
||||
$cache->preload($cacheNames);
|
||||
|
||||
$modules = null;
|
||||
try {
|
||||
|
@@ -122,6 +122,14 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
||||
*/
|
||||
protected $variableCache = array();
|
||||
|
||||
/**
|
||||
* Cached InnoDB stopwords (keys are the stopwords and values are irrelevant)
|
||||
*
|
||||
* @var array|null Becomes array once loaded
|
||||
*
|
||||
*/
|
||||
protected $stopwordCache = null;
|
||||
|
||||
/**
|
||||
* Create a new PDO instance from ProcessWire $config API variable
|
||||
*
|
||||
@@ -766,6 +774,42 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
||||
return in_array($str, $operators, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is given word a fulltext stopword to the current database engine?
|
||||
*
|
||||
* @param string $word
|
||||
* @return bool
|
||||
* @since 3.0.160
|
||||
*
|
||||
*/
|
||||
public function isStopword($word) {
|
||||
|
||||
if($this->engine === 'myisam') {
|
||||
return DatabaseStopwords::has($word);
|
||||
}
|
||||
|
||||
if($this->stopwordCache === null && $this->engine === 'innodb') {
|
||||
$cache = $this->wire()->cache;
|
||||
$stopwords = null;
|
||||
if($cache) {
|
||||
$stopwords = $cache->get('InnoDB.stopwords');
|
||||
if($stopwords) $stopwords = explode(',', $stopwords);
|
||||
}
|
||||
if(!$stopwords) {
|
||||
$query = $this->prepare('SELECT value FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD');
|
||||
$query->execute();
|
||||
$stopwords = $query->fetchAll(\PDO::FETCH_COLUMN, 0);
|
||||
$query->closeCursor();
|
||||
if($cache) $cache->save('InnoDB.stopwords', implode(',', $stopwords), WireCache::expireDaily);
|
||||
}
|
||||
$this->stopwordCache = array_flip($stopwords);
|
||||
}
|
||||
|
||||
if(!$this->stopwordCache) return false;
|
||||
|
||||
return isset($this->stopwordCache[strtolower($word)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a table name for _a-zA-Z0-9
|
||||
*
|
||||
@@ -930,6 +974,28 @@ class WireDatabasePDO extends Wire implements WireDatabase {
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current database engine (lowercase)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.160
|
||||
*
|
||||
*/
|
||||
public function getEngine() {
|
||||
return $this->engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current database charset (lowercase)
|
||||
*
|
||||
* @return string
|
||||
* @since 3.0.160
|
||||
*
|
||||
*/
|
||||
public function getCharset() {
|
||||
return $this->charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve new instance of WireDatabaseBackups ready to use with this connection
|
||||
*
|
||||
|
@@ -129,15 +129,27 @@ class WireDatabasePDOStatement extends \PDOStatement {
|
||||
*
|
||||
* @param array|null $input_parameters
|
||||
* @return bool
|
||||
* @throws \PDOException
|
||||
*
|
||||
*/
|
||||
public function execute($input_parameters = NULL) {
|
||||
|
||||
$timer = Debug::startTimer();
|
||||
$result = parent::execute($input_parameters);
|
||||
$exception = null;
|
||||
|
||||
try {
|
||||
$result = parent::execute($input_parameters);
|
||||
} catch(\PDOException $e) {
|
||||
$exception = $e;
|
||||
$result = false;
|
||||
}
|
||||
|
||||
$timer = Debug::stopTimer($timer, 'ms');
|
||||
|
||||
if(!$this->database) return $result;
|
||||
if(!$this->database) {
|
||||
if($exception) throw $exception;
|
||||
return $result;
|
||||
}
|
||||
|
||||
if(is_array($input_parameters)) {
|
||||
foreach($input_parameters as $key => $value) {
|
||||
@@ -146,6 +158,7 @@ class WireDatabasePDOStatement extends \PDOStatement {
|
||||
}
|
||||
|
||||
$debugNote = trim("$this->debugNote [$timer]");
|
||||
if($exception) $debugNote .= ' FAIL SQLSTATE[' . $exception->getCode() . ']';
|
||||
|
||||
if($this->debugParamsQty) {
|
||||
$sql = $this->queryString;
|
||||
@@ -168,6 +181,8 @@ class WireDatabasePDOStatement extends \PDOStatement {
|
||||
$this->database->queryLog($this->queryString, $debugNote);
|
||||
}
|
||||
|
||||
if($exception) throw $exception;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
@@ -913,8 +913,8 @@ class FieldtypeFile extends FieldtypeMulti implements ConfigurableModule {
|
||||
} else if($operator === '!=' && ctype_alnum("$value")) {
|
||||
$operator = '!~='; // ok
|
||||
|
||||
} else if($operator === '~=' || $operator === '!~=' || $operator === '%=' || $operator === '*=') {
|
||||
// ok
|
||||
} else if(Selectors::getSelectorByOperator($operator, 'compareType') & Selector::compareTypeFind) {
|
||||
// ok, text finding operators
|
||||
|
||||
} else {
|
||||
throw new PageFinderSyntaxException("Operator $operator is not supported by $this in selector: $selector");
|
||||
|
Reference in New Issue
Block a user