mirror of
https://github.com/silverstripe/silverstripe-framework
synced 2024-10-22 14:05:37 +02:00
(merged from branches/roa. use "svn log -c <changeset> -g <module-svn-path>" for detailed commit message)
git-svn-id: svn://svn.silverstripe.com/silverstripe/open/modules/sapphire/trunk@60276 467b73ca-7a2a-4603-9d3b-597d59a354a9
This commit is contained in:
parent
124a6e3934
commit
bf9f349210
@ -62,6 +62,16 @@ abstract class DataFormatter extends Object {
|
||||
*/
|
||||
protected $outputContentType = null;
|
||||
|
||||
/**
|
||||
* Used to set totalSize properties on the output
|
||||
* of {@link convertDataObjectSet()}, shows the
|
||||
* total number of records without the "limit" and "offset"
|
||||
* GET parameters. Useful to implement pagination.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $totalSize;
|
||||
|
||||
/**
|
||||
* Get a DataFormatter object suitable for handling the given file extension.
|
||||
*
|
||||
@ -182,6 +192,20 @@ abstract class DataFormatter extends Object {
|
||||
return $this->outputContentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
*/
|
||||
public function setTotalSize($size) {
|
||||
$this->totalSize = (int)$size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTotalSize() {
|
||||
return $this->totalSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all fields on the object which should be shown
|
||||
* in the output. Can be customised through {@link self::setCustomFields()}.
|
||||
|
@ -90,7 +90,14 @@ class JSONDataFormatter extends DataFormatter {
|
||||
foreach($set as $item) {
|
||||
if($item->canView()) $jsonParts[] = $this->convertDataObject($item);
|
||||
}
|
||||
return "[\n" . implode(",\n", $jsonParts) . "\n]";
|
||||
$json = "{\n";
|
||||
$json .= 'totalSize: ';
|
||||
$json .= (is_numeric($this->totalSize)) ? $this->totalSize : 'null';
|
||||
$json .= ",\n";
|
||||
$json .= "items: [\n" . implode(",\n", $jsonParts) . "\n]\n";
|
||||
$json .= "}\n";
|
||||
|
||||
return $json;
|
||||
}
|
||||
|
||||
public function convertStringToArray($strData) {
|
||||
|
@ -140,7 +140,7 @@ class RestfulServer extends Controller {
|
||||
* @param String $relation
|
||||
* @return String The serialized representation of the requested object(s) - usually XML or JSON.
|
||||
*/
|
||||
protected function getHandler($className, $id, $relation) {
|
||||
protected function getHandler($className, $id, $relationName) {
|
||||
$sort = array(
|
||||
'sort' => $this->request->getVar('sort'),
|
||||
'dir' => $this->request->getVar('dir')
|
||||
@ -150,44 +150,45 @@ class RestfulServer extends Controller {
|
||||
'limit' => $this->request->getVar('limit')
|
||||
);
|
||||
|
||||
$params = $this->request->getVars();
|
||||
|
||||
$responseFormatter = $this->getResponseDataFormatter();
|
||||
if(!$responseFormatter) return $this->unsupportedMediaType();
|
||||
|
||||
// $obj can be either a DataObject or a DataObjectSet,
|
||||
// depending on the request
|
||||
if($id) {
|
||||
$obj = DataObject::get_by_id($className, $id);
|
||||
// Format: /api/v1/<MyClass>/<ID>
|
||||
$query = $this->getObjectQuery($className, $id, $params);
|
||||
$obj = singleton($className)->buildDataObjectSet($query->execute());
|
||||
if(!$obj) return $this->notFound();
|
||||
$obj = $obj->First();
|
||||
if(!$obj->canView()) return $this->permissionFailure();
|
||||
|
||||
if($relation) {
|
||||
if($relationClass = $obj->many_many($relation)) {
|
||||
$query = $obj->getManyManyComponentsQuery($relation);
|
||||
} elseif($relationClass = $obj->has_many($relation)) {
|
||||
$query = $obj->getComponentsQuery($relation);
|
||||
} elseif($relationClass = $obj->has_one($relation)) {
|
||||
$query = null;
|
||||
} elseif($obj->hasMethod("{$relation}Query")) {
|
||||
// @todo HACK Switch to ComponentSet->getQuery() once we implement it (and lazy loading)
|
||||
$query = $obj->{"{$relation}Query"}(null, $sort, null, $limit);
|
||||
$relationClass = $obj->{"{$relation}Class"}();
|
||||
} else {
|
||||
return $this->notFound();
|
||||
}
|
||||
|
||||
// get all results
|
||||
$obj = $this->search($relationClass, $this->request->getVars(), $sort, $limit, $query);
|
||||
if(!$obj) $obj = new DataObjectSet();
|
||||
// Format: /api/v1/<MyClass>/<ID>/<Relation>
|
||||
if($relationName) {
|
||||
$query = $this->getObjectRelationQuery($obj, $params, $sort, $limit, $relationName);
|
||||
if($query === false) return $this->notFound();
|
||||
$obj = singleton($className)->buildDataObjectSet($query->execute());
|
||||
}
|
||||
|
||||
} else {
|
||||
$obj = $this->search($className, $this->request->getVars(), $sort, $limit);
|
||||
// Format: /api/v1/<MyClass>
|
||||
$query = $this->getObjectsQuery($className, $params, $sort, $limit);
|
||||
$obj = singleton($className)->buildDataObjectSet($query->execute());
|
||||
|
||||
// show empty serialized result when no records are present
|
||||
if(!$obj) $obj = new DataObjectSet();
|
||||
}
|
||||
|
||||
$this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());
|
||||
|
||||
if($obj instanceof DataObjectSet) return $responseFormatter->convertDataObjectSet($obj);
|
||||
else return $responseFormatter->convertDataObject($obj);
|
||||
if($obj instanceof DataObjectSet) {
|
||||
$responseFormatter->setTotalSize($query->unlimitedRowCount());
|
||||
return $responseFormatter->convertDataObjectSet($obj);
|
||||
} else {
|
||||
return $responseFormatter->convertDataObject($obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -202,7 +203,7 @@ class RestfulServer extends Controller {
|
||||
* @param array $params
|
||||
* @return DataObjectSet
|
||||
*/
|
||||
protected function search($className, $params = null, $sort = null, $limit = null, $existingQuery = null) {
|
||||
protected function getSearchQuery($className, $params = null, $sort = null, $limit = null, $existingQuery = null) {
|
||||
if(singleton($className)->hasMethod('getRestfulSearchContext')) {
|
||||
$searchContext = singleton($className)->{'getRestfulSearchContext'}();
|
||||
} else {
|
||||
@ -210,7 +211,7 @@ class RestfulServer extends Controller {
|
||||
}
|
||||
$query = $searchContext->getQuery($params, $sort, $limit, $existingQuery);
|
||||
|
||||
return singleton($className)->buildDataObjectSet($query->execute());
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -355,6 +356,61 @@ class RestfulServer extends Controller {
|
||||
return $obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single DataObject by ID,
|
||||
* through a request like /api/v1/<MyClass>/<MyID>
|
||||
*
|
||||
* @param string $className
|
||||
* @param int $id
|
||||
* @param array $params
|
||||
* @return SQLQuery
|
||||
*/
|
||||
protected function getObjectQuery($className, $id, $params) {
|
||||
$baseClass = ClassInfo::baseDataClass($className);
|
||||
return singleton($className)->buildSQL(
|
||||
"`$baseClass`.ID = {$id}"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DataObject $obj
|
||||
* @param array $params
|
||||
* @param int|array $sort
|
||||
* @param int|array $limit
|
||||
* @return SQLQuery
|
||||
*/
|
||||
protected function getObjectsQuery($className, $params, $sort, $limit) {
|
||||
return $this->getSearchQuery($className, $params, $sort, $limit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DataObject $obj
|
||||
* @param array $params
|
||||
* @param int|array $sort
|
||||
* @param int|array $limit
|
||||
* @param string $relationName
|
||||
* @return SQLQuery|boolean
|
||||
*/
|
||||
protected function getObjectRelationQuery($obj, $params, $sort, $limit, $relationName) {
|
||||
if($relationClass = $obj->many_many($relationName)) {
|
||||
$query = $obj->getManyManyComponentsQuery($relationName);
|
||||
} elseif($relationClass = $obj->has_many($relationName)) {
|
||||
$query = $obj->getComponentsQuery($relationName);
|
||||
} elseif($relationClass = $obj->has_one($relationName)) {
|
||||
$query = null;
|
||||
} elseif($obj->hasMethod("{$relation}Query")) {
|
||||
// @todo HACK Switch to ComponentSet->getQuery() once we implement it (and lazy loading)
|
||||
$query = $obj->{"{$relation}Query"}(null, $sort, null, $limit);
|
||||
$relationClass = $obj->{"{$relation}Class"}();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// get all results
|
||||
return $this->getSearchQuery($relationClass, $params, $sort, $limit);
|
||||
}
|
||||
|
||||
protected function permissionFailure() {
|
||||
// return a 401
|
||||
$this->getResponse()->setStatusCode(403);
|
||||
|
@ -96,7 +96,8 @@ class XMLDataFormatter extends DataFormatter {
|
||||
Controller::curr()->getResponse()->addHeader("Content-type", "text/xml");
|
||||
$className = $set->class;
|
||||
|
||||
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<$className>\n";
|
||||
$xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
|
||||
$xml .= (is_numeric($this->totalSize)) ? "<$className totalSize=\"{$this->totalSize}\">\n" : "<$className>\n";
|
||||
foreach($set as $item) {
|
||||
if($item->canView()) $xml .= $this->convertDataObjectWithoutHeader($item);
|
||||
}
|
||||
|
@ -105,7 +105,7 @@ require_once(MANIFEST_FILE);
|
||||
|
||||
if(isset($_GET['debugmanifest'])) Debug::show(file_get_contents(MANIFEST_FILE));
|
||||
|
||||
if(!isset(Director::$environment_type) && $envType) Director::set_environment_type($envType);
|
||||
//if(!isset(Director::$environment_type) && $envType) Director::set_environment_type($envType);
|
||||
|
||||
// Load error handlers
|
||||
Debug::loadErrorHandlers();
|
||||
|
@ -11,7 +11,12 @@
|
||||
* This is loaded into the TEMP_FOLDER define on start up
|
||||
*/
|
||||
function getTempFolder() {
|
||||
$cachefolder = "silverstripe-cache" . str_replace(array("/",":", "\\"),"-", substr($_SERVER['SCRIPT_FILENAME'], 0, strlen($_SERVER['SCRIPT_FILENAME']) - strlen('/sapphire/main.php')));
|
||||
if(preg_match('/^(.*)\/sapphire\/[^\/]+$/', $_SERVER['SCRIPT_FILENAME'], $matches)) {
|
||||
$cachefolder = "silverstripe-cache" . str_replace(array(' ',"/",":", "\\"),"-", $matches[1]);
|
||||
} else {
|
||||
$cachefolder = "silverstripe-cache";
|
||||
}
|
||||
|
||||
$ssTmp = dirname(dirname($_SERVER['SCRIPT_FILENAME'])) . "/silverstripe-cache";
|
||||
if(@file_exists($ssTmp)) {
|
||||
return $ssTmp;
|
||||
|
@ -2,7 +2,7 @@
|
||||
/**
|
||||
* Define a constant for the name of the manifest file
|
||||
*/
|
||||
define("MANIFEST_FILE", TEMP_FOLDER . "/manifest" . str_replace(array(' ','\\','/',':'),"_", $_SERVER['SCRIPT_FILENAME']));
|
||||
define("MANIFEST_FILE", TEMP_FOLDER . "/manifest-" . str_replace('.php','',basename($_SERVER['SCRIPT_FILENAME'])));
|
||||
|
||||
/**
|
||||
* The ManifestBuilder class generates the manifest file and keeps it fresh.
|
||||
|
@ -80,6 +80,13 @@ class HTTPResponse extends Object {
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this HTTP response is in error
|
||||
*/
|
||||
function isError() {
|
||||
return $this->statusCode && ($this->statusCode < 200 || $this->statusCode > 399);
|
||||
}
|
||||
|
||||
function setBody($body) {
|
||||
$this->body = $body;
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class RequestHandlingData extends ViewableData {
|
||||
foreach($this->stat('url_handlers') as $rule => $action) {
|
||||
if(isset($_REQUEST['debug_request'])) Debug::message("Testing '$rule' with '" . $request->remaining() . "' on $this->class");
|
||||
if($params = $request->match($rule, true)) {
|
||||
if(isset($_REQUEST['debug_request'])) Debug::message("Rule '$rule' matched on $this->class");
|
||||
if(isset($_REQUEST['debug_request'])) Debug::message("Rule '$rule' matched to action '$action' on $this->class");
|
||||
|
||||
// Actions can reference URL parameters, eg, '$Action/$ID/$OtherID' => '$Action',
|
||||
if($action[0] == '$') $action = $params[substr($action,1)];
|
||||
@ -86,6 +86,11 @@ class RequestHandlingData extends ViewableData {
|
||||
return $this->httpError(403, "Action '$action' isn't allowed on class $this->class");
|
||||
}
|
||||
|
||||
if($result instanceof HTTPResponse && $result->isError()) {
|
||||
if(isset($_REQUEST['debug_request'])) Debug::message("Rule resulted in HTTP error; breaking");
|
||||
return $result;
|
||||
}
|
||||
|
||||
// If we return a RequestHandlingData, call handleRequest() on that, even if there is no more URL to parse.
|
||||
// It might have its own handler. However, we only do this if we haven't just parsed an empty rule ourselves,
|
||||
// to prevent infinite loops
|
||||
|
@ -2630,7 +2630,7 @@ class DataObject extends ViewableData implements DataObjectInterface {
|
||||
* User defined permissions for search result table by ModelAdmin to act on.
|
||||
* Such as print search
|
||||
*/
|
||||
public static $results_permissions = null;
|
||||
public static $results_permissions = array();
|
||||
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,7 @@ class PrimaryKey extends Int {
|
||||
public function scaffoldFormField($title = null) {
|
||||
$objs = DataObject::get($this->object->class);
|
||||
|
||||
$first = $objs->First();
|
||||
$titleField = isset($first->Title) ? "Title" : "Name";
|
||||
$titleField = (singleton($this->object->class)->hasField('Title')) ? "Title" : "Name";
|
||||
|
||||
$map = ($objs) ? $objs->toDropdownMap("ID", $titleField) : false;
|
||||
|
||||
|
@ -23,6 +23,10 @@ table.CMSList td {
|
||||
border-style:none;
|
||||
}
|
||||
|
||||
.TableListField table.data td.nolabel{
|
||||
display: none;
|
||||
}
|
||||
|
||||
table.TableField th,
|
||||
table.TableListField th,
|
||||
.TableListField table.data th,
|
||||
@ -114,7 +118,7 @@ table.CMSList tbody td.checkbox {
|
||||
table.TableField tbody tr.over td,
|
||||
.TableListField table.data tbody tr.over td,
|
||||
table.CMSList tbody td.over td{
|
||||
background-color: #FFC;
|
||||
background-color: #FF6600;
|
||||
}
|
||||
|
||||
table.TableField tbody tr.current td,
|
||||
|
@ -12,11 +12,17 @@ class TaskRunner extends Controller {
|
||||
|
||||
function index() {
|
||||
$tasks = ClassInfo::subclassesFor('BuildTask');
|
||||
echo "<ul>";
|
||||
foreach($tasks as $task) {
|
||||
echo "<li><a href=\"$task\">$task</a></li>";
|
||||
if(Director::is_cli()) {
|
||||
echo "Tasks available:\n\n";
|
||||
foreach($tasks as $task) echo " * $task: sake dev/tasks/$task\n";
|
||||
} else {
|
||||
echo "<h1>Tasks available</h1>\n";
|
||||
echo "<ul>";
|
||||
foreach($tasks as $task) {
|
||||
echo "<li><a href=\"$task\">$task</a></li>\n";
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
echo "</ul>";
|
||||
}
|
||||
|
||||
function runTask($request) {
|
||||
@ -29,6 +35,8 @@ class TaskRunner extends Controller {
|
||||
if (!$task->isDisabled()) $task->run($request);
|
||||
} else {
|
||||
echo "Build task '$TaskName' not found.";
|
||||
if(class_exists($TaskName)) echo " It isn't a subclass of BuildTask.";
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,7 +96,7 @@ class CheckboxSetField extends OptionsetField {
|
||||
|
||||
$this->disabled ? $disabled = " disabled=\"disabled\"" : $disabled = "";
|
||||
|
||||
$options .= "<li class=\"$extraClass\"><input id=\"$itemID\" name=\"$this->name[]\" type=\"checkbox\" value=\"$key\"$checked $disabled class=\"checkbox\" /> <label for=\"$itemID\">$value</label></li>\n";
|
||||
$options .= "<li class=\"$extraClass\"><input id=\"$itemID\" name=\"$this->name[$key]\" type=\"checkbox\" value=\"$key\"$checked $disabled class=\"checkbox\" /> <label for=\"$itemID\">$value</label></li>\n";
|
||||
}
|
||||
|
||||
|
||||
|
@ -185,44 +185,6 @@ JS;
|
||||
return $this->renderWith($this->template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns non-paginated items.
|
||||
* Please use Items() for pagination.
|
||||
* This function is called whenever a complete result-set is needed,
|
||||
* so even if a single record is displayed in a popup, we need the results
|
||||
* to make pagination work.
|
||||
*
|
||||
* @todo Merge with more efficient querying of TableListField
|
||||
*/
|
||||
function sourceItems() {
|
||||
if($this->sourceItems) {
|
||||
return $this->sourceItems;
|
||||
}
|
||||
|
||||
$limitClause = "";
|
||||
if($this->pageSize) {
|
||||
$limitClause = "{$this->pageSize}";
|
||||
} else {
|
||||
$limitClause = "0";
|
||||
}
|
||||
if(isset($_REQUEST['ctf'][$this->Name()]['start']) && is_numeric($_REQUEST['ctf'][$this->Name()]['start'])) {
|
||||
$SQL_start = intval($_REQUEST['ctf'][$this->Name()]['start']);
|
||||
$limitClause .= " OFFSET {$SQL_start}";
|
||||
}
|
||||
|
||||
$sort = $this->sourceSort;
|
||||
if(isset($_REQUEST['ctf'][$this->Name()]['sort'])) {
|
||||
$sort = Convert::raw2sql($_REQUEST['ctf'][$this->Name()]['sort']);
|
||||
}
|
||||
|
||||
$this->sourceItems = DataObject::get($this->sourceClass, $this->sourceFilter, $sort, $this->sourceJoin, $limitClause);
|
||||
$this->unpagedSourceItems = DataObject::get($this->sourceClass, $this->sourceFilter, $sort, $this->sourceJoin);
|
||||
|
||||
$this->totalCount = ($this->unpagedSourceItems) ? $this->unpagedSourceItems->TotalItems() : null;
|
||||
|
||||
return $this->sourceItems;
|
||||
}
|
||||
|
||||
function sourceClass() {
|
||||
return $this->sourceClass;
|
||||
}
|
||||
|
@ -1045,6 +1045,8 @@ class TableListField_Item extends ViewableData {
|
||||
function Fields() {
|
||||
$list = $this->parent->FieldList();
|
||||
foreach($list as $fieldName => $fieldTitle) {
|
||||
$value = "";
|
||||
|
||||
// This supports simple FieldName syntax
|
||||
if(strpos($fieldName,'.') === false) {
|
||||
$value = ($this->item->val($fieldName)) ? $this->item->val($fieldName) : $this->item->$fieldName;
|
||||
|
@ -272,5 +272,5 @@ TableListRecord.prototype = {
|
||||
}
|
||||
}
|
||||
|
||||
//TableListRecord.applyTo('div.TableListField tr');
|
||||
TableListRecord.applyTo('div.TableListField tr');
|
||||
TableListField.applyTo('div.TableListField');
|
||||
|
@ -114,18 +114,14 @@ class SearchContext extends Object {
|
||||
$SQL_sort = (!empty($sort)) ? Convert::raw2sql($sort) : singleton($this->modelClass)->stat('default_sort');
|
||||
$query->orderby($SQL_sort);
|
||||
foreach($searchParams as $key => $value) {
|
||||
/*We add $value!='' here to not include a filter like this: $fieldname like '%%', which abviously filter out some
|
||||
records with the $fieldname set to null. and this is not the search intention.
|
||||
*/
|
||||
if ($value != '0'&&$value!='') {
|
||||
$key = str_replace('__', '.', $key);
|
||||
$filter = $this->getFilter($key);
|
||||
if ($filter) {
|
||||
$filter->setModel($this->modelClass);
|
||||
$filter->setValue($value);
|
||||
$key = str_replace('__', '.', $key);
|
||||
if($filter = $this->getFilter($key)) {
|
||||
$filter->setModel($this->modelClass);
|
||||
$filter->setValue($value);
|
||||
if(! $filter->isEmpty()) {
|
||||
$filter->apply($query);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
return $query;
|
||||
|
@ -28,5 +28,8 @@ class EndsWithFilter extends SearchFilter {
|
||||
$query->where($this->getDbName(), "RLIKE", "{$this->getValue()}$");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -21,11 +21,12 @@ class ExactMatchFilter extends SearchFilter {
|
||||
* @return unknown
|
||||
*/
|
||||
public function apply(SQLQuery $query) {
|
||||
if($this->getValue()) {
|
||||
$query = $this->applyRelation($query);
|
||||
return $query->where("{$this->getDbName()} = '{$this->getValue()}'");
|
||||
}
|
||||
$query = $this->applyRelation($query);
|
||||
return $query->where("{$this->getDbName()} = '{$this->getValue()}'");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -13,22 +13,23 @@
|
||||
class ExactMatchMultiFilter extends SearchFilter {
|
||||
|
||||
public function apply(SQLQuery $query) {
|
||||
if($this->getValue()) {
|
||||
$query = $this->applyRelation($query);
|
||||
$values = explode(',',$this->getValue());
|
||||
if(!$values) return false;
|
||||
|
||||
for($i=0; $i<count($values); $i++) {
|
||||
if(!is_numeric($values[$i])) {
|
||||
// @todo Fix string replacement to only replace leading and tailing quotes
|
||||
$values[$i] = str_replace("'", '', $values[$i]);
|
||||
$values[$i] = Convert::raw2sql($values[$i]);
|
||||
}
|
||||
$query = $this->applyRelation($query);
|
||||
$values = explode(',',$this->getValue());
|
||||
if(! $values) return false;
|
||||
for($i = 0; $i < count($values); $i++) {
|
||||
if(! is_numeric($values[$i])) {
|
||||
// @todo Fix string replacement to only replace leading and tailing quotes
|
||||
$values[$i] = str_replace("'", '', $values[$i]);
|
||||
$values[$i] = Convert::raw2sql($values[$i]);
|
||||
}
|
||||
$SQL_valueStr = "'" . implode("','", $values) . "'";
|
||||
return $query->where("{$this->getDbName()} IN ({$SQL_valueStr})");
|
||||
}
|
||||
$SQL_valueStr = "'" . implode("','", $values) . "'";
|
||||
|
||||
return $query->where("{$this->getDbName()} IN ({$SQL_valueStr})");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -32,5 +32,8 @@ class FulltextFilter extends SearchFilter {
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
24
search/filters/GreaterThanFilter.php
Normal file
24
search/filters/GreaterThanFilter.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* Selects numerical/date content greater than the input
|
||||
*
|
||||
* @todo documentation
|
||||
*
|
||||
* @package sapphire
|
||||
* @subpackage search
|
||||
*/
|
||||
class GreaterThanFilter extends SearchFilter {
|
||||
|
||||
/**
|
||||
* @return $query
|
||||
*/
|
||||
public function apply(SQLQuery $query) {
|
||||
$query = $this->applyRelation($query);
|
||||
return $query->where("{$this->getDbName()} > '{$this->getValue()}'");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
24
search/filters/LessThanFilter.php
Normal file
24
search/filters/LessThanFilter.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
/**
|
||||
* Selects numerical/date content smaller than the input
|
||||
*
|
||||
* @todo documentation
|
||||
*
|
||||
* @package sapphire
|
||||
* @subpackage search
|
||||
*/
|
||||
class LessThanFilter extends SearchFilter {
|
||||
|
||||
/**
|
||||
* @return $query
|
||||
*/
|
||||
public function apply(SQLQuery $query) {
|
||||
$query = $this->applyRelation($query);
|
||||
return $query->where("{$this->getDbName()} < '{$this->getValue()}'");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -17,5 +17,8 @@ class PartialMatchFilter extends SearchFilter {
|
||||
return $query->where("{$this->getDbName()} LIKE '%{$this->getValue()}%'");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -139,5 +139,19 @@ abstract class SearchFilter extends Object {
|
||||
*/
|
||||
abstract public function apply(SQLQuery $query);
|
||||
|
||||
/**
|
||||
* Determines if a field has a value,
|
||||
* and that the filter should be applied.
|
||||
* Relies on the field being populated with
|
||||
* {@link setValue()}
|
||||
*
|
||||
* @usedby SearchContext
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEmpty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
23
search/filters/SmallerThanFilter.php
Normal file
23
search/filters/SmallerThanFilter.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Selects numerical/date content smaller than the input
|
||||
*
|
||||
* @todo documentation
|
||||
*
|
||||
* @package sapphire
|
||||
* @subpackage search
|
||||
*/
|
||||
class SmallerThanFilter extends SearchFilter {
|
||||
|
||||
/**
|
||||
* @return $query
|
||||
*/
|
||||
public function apply(SQLQuery $query) {
|
||||
if($this->getValue()) {
|
||||
$query = $this->applyRelation($query);
|
||||
return $query->where("{$this->getDbName()} < '{$this->getValue()}'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
?>
|
@ -28,5 +28,8 @@ class StartsWithFilter extends SearchFilter {
|
||||
$query->where("LOCATE('{$this->getValue()}', {$this->getDbName()}) = 1");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -13,17 +13,19 @@
|
||||
class StartsWithMultiFilter extends SearchFilter {
|
||||
|
||||
public function apply(SQLQuery $query) {
|
||||
if($this->getValue()) {
|
||||
$query = $this->applyRelation($query);
|
||||
$values = explode(',',$this->getValue());
|
||||
$query = $this->applyRelation($query);
|
||||
$values = explode(',', $this->getValue());
|
||||
|
||||
foreach($values as $value) {
|
||||
$SQL_value = Convert::raw2sql(str_replace("'", '', $value));
|
||||
$matches[] = "{$this->getDbName()} LIKE '$SQL_value%'";
|
||||
}
|
||||
return $query->where(implode(" OR ", $matches));
|
||||
foreach($values as $value) {
|
||||
$SQL_value = Convert::raw2sql(str_replace("'", '', $value));
|
||||
$matches[] = "{$this->getDbName()} LIKE '$SQL_value%'";
|
||||
}
|
||||
|
||||
return $query->where(implode(" OR ", $matches));
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
?>
|
@ -16,6 +16,9 @@ class SubstringFilter extends SearchFilter {
|
||||
return $query->where("LOCATE('{$this->getValue()}', {$this->getDbName()}) != 0");
|
||||
}
|
||||
|
||||
public function isEmpty() {
|
||||
return $this->getValue() == null || $this->getValue() == '';
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user