Last active
January 11, 2016 15:39
-
-
Save ionas/10b8f0bb847d48028bc2 to your computer and use it in GitHub Desktop.
An CakePHP3 autosearch behavior for the friendsofcake/search plugin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Model\Behavior; | |
use Cake\ORM\Behavior; | |
/** | |
* AutoSearch behavior | |
*/ | |
class AutoSearchBehavior extends Behavior | |
{ | |
/** | |
* Constructor hook method. | |
* | |
* Implement this method to avoid having to overwrite | |
* the constructor and call parent. | |
* | |
* @param array $config The configuration settings provided to this behavior. | |
* @return void | |
*/ | |
public function initialize(array $config) | |
{ | |
parent::initialize($config); | |
if ($this->_isBake()) { | |
return; | |
} | |
$this->setupSearch(); | |
} | |
public function setupSearch() { | |
$table = $this->_table; | |
$columns = $table->schema()->typeMap(); | |
foreach ($table->associations() as $association) { | |
if ($association->type() == 'manyToOne') { | |
$table->searchManager()->add( | |
$association->aliasField($association->displayField()), 'Search.Like', [ | |
'field' => $association->aliasField($association->displayField()), | |
'filterEmpty' => true, | |
'before' => true, | |
'after' => true, | |
]); | |
unset($columns[$association->foreignKey()]); | |
} | |
} | |
foreach ($columns as $columnName => $columnType) { | |
if (strpos($columnType, 'integer') !== false) { | |
$table->searchManager()->add($columnName, 'Search.Like', [ | |
'field' => $table->aliasField($columnName), | |
'filterEmpty' => true, | |
]); | |
} elseif ($columnType === 'boolean') { | |
$table->searchManager()->add($columnName, 'Search.Value', [ | |
'field' => $table->aliasField($columnName), | |
'filterEmpty' => false, | |
]); | |
} else { | |
$table->searchManager()->add($columnName, 'Search.Like', [ | |
'field' => [$table->aliasField($columnName)], | |
'filterEmpty' => true, | |
'before' => true, | |
'after' => true, | |
]); | |
} | |
} | |
} | |
private function _isBake() { | |
global $argv; | |
if (PHP_SAPI === 'cli' && $argv[1] === 'bake') { | |
return true; | |
} | |
return false; | |
} | |
} |
Update:
- Behavior does not run during bake time (crashes on recursion).
- Integers are filtered by LIKE, too.
- EDIT: BROKEN, see BELOW for a working version.
- Update stopping recursion on self-joining models (with help by savant 💯xTHX)
<?php
namespace App\Model\Behavior;
use Cake\ORM\Behavior;
/**
* AutoSearch behavior
*/
class AutoSearchBehavior extends Behavior
{
/**
* Constructor hook method.
*
* Implement this method to avoid having to overwrite
* the constructor and call parent.
*
* @param array $config The configuration settings provided to this behavior.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
if ($this->_isBake()) {
return;
}
$this->setupSearch();
}
public function setupSearch() {
$table = $this->_table;
$columns = $table->schema()->typeMap();
foreach ($table->associations() as $association) {
if ($association->type() !== 'manyToOne') {
break;
}
if (($table instanceof \App\Model\Table) === false) {
break;
}
$associationClass = get_class($association);
$displayField = $table->displayField();
$field = $table->aliasField($displayField);
$foreignKey = $table->foreignKey();
if ($currentClass !== $associationClass) {
$displayField = $association->displayField();
$field = $association->aliasField($displayField);
$foreignKey = $association->foreignKey();
}
$table->searchManager()->add(
$association->aliasField($displayField),
'Search.Like',
[
'field' => $field,
'filterEmpty' => true,
'before' => true,
'after' => true,
]
);
unset($columns[$foreignKey]);
}
foreach ($columns as $columnName => $columnType) {
if (strpos($columnType, 'integer') !== false) {
$table->searchManager()->add($columnName, 'Search.Like', [
'field' => $table->aliasField($columnName),
'filterEmpty' => true,
]);
} elseif ($columnType === 'boolean') {
$table->searchManager()->add($columnName, 'Search.Value', [
'field' => $table->aliasField($columnName),
'filterEmpty' => false,
]);
} else {
$table->searchManager()->add($columnName, 'Search.Like', [
'field' => [$table->aliasField($columnName)],
'filterEmpty' => true,
'before' => true,
'after' => true,
]);
}
}
}
private function _isBake() {
global $argv;
if (PHP_SAPI === 'cli' && $argv[1] === 'bake') {
return true;
}
return false;
}
}
Above code does not run. This runs (interim solution):
<?php
namespace App\Model\Behavior;
use Cake\ORM\Behavior;
/**
* AutoSearch behavior
*/
class AutoSearchBehavior extends Behavior
{
/**
* Constructor hook method.
*
* Implement this method to avoid having to overwrite
* the constructor and call parent.
*
* @param array $config The configuration settings provided to this behavior.
* @return void
*/
public function initialize(array $config)
{
parent::initialize($config);
if ($this->_isBake()) {
return;
}
$this->setupSearch();
}
public function setupSearch() {
$tableClass = $this->_table;
$columns = $tableClass->schema()->typeMap();
foreach ($tableClass->associations() as $associationKey => $association) {
if (strpos($association->name(), 'Parent') === 0 || strpos($association->name(), 'Child') === 0) {
break;
}
// foreach ($association->source()->associations() as $nestedAssociation) {
// if ($association->name() === $nestedAssociation->name()) {
// break 2;
// }
// }
if ($association->type() == 'manyToOne') {
$tableClass->searchManager()->add(
$association->aliasField($association->displayField()), 'Search.Like', [
'field' => $association->aliasField($association->displayField()),
'filterEmpty' => true,
'before' => true,
'after' => true,
]);
unset($columns[$association->foreignKey()]);
}
}
foreach ($columns as $columnName => $columnType) {
if (strpos($columnType, 'integer') !== false) {
$tableClass->searchManager()->add($columnName, 'Search.Like', [
'field' => $tableClass->aliasField($columnName),
'filterEmpty' => true,
]);
} elseif ($columnType === 'boolean') {
$tableClass->searchManager()->add($columnName, 'Search.Value', [
'field' => $tableClass->aliasField($columnName),
'filterEmpty' => false,
]);
} else {
$tableClass->searchManager()->add($columnName, 'Search.Like', [
'field' => [$tableClass->aliasField($columnName)],
'filterEmpty' => true,
'before' => true,
'after' => true,
]);
}
}
}
private function _isBake() {
global $argv;
if (PHP_SAPI === 'cli' && $argv[1] === 'bake') {
return true;
}
return false;
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Vanilla interface (@2015-12-22 dev-master) towards friendsofcake/search, except that you are required to...
$this->Form->input('Authors.name')
, and...filterParams()
with aHash::flatten()
like so:$this->Post->filterParams(Hash::flatten($this->request->query))
.