Converted to PSR-2

This commit is contained in:
helpfulrobot 2015-11-18 17:05:38 +13:00
parent d70a61ae98
commit 48a07375a0
4 changed files with 1045 additions and 977 deletions

View File

@ -9,314 +9,332 @@
* @package forms * @package forms
* @subpackage fields * @subpackage fields
*/ */
class StringTagField extends DropdownField { class StringTagField extends DropdownField
/** {
* @var array /**
*/ * @var array
public static $allowed_actions = array( */
'suggest', public static $allowed_actions = array(
); 'suggest',
);
/**
* @var bool
*/
protected $shouldLazyLoad = false;
/**
* @var int
*/
protected $lazyLoadItemLimit = 10;
/**
* @var null|DataObject
*/
protected $record;
/**
* @var bool
*/
protected $isMultiple = true;
/**
* @param string $name
* @param string $title
* @param array|SS_List $source
* @param array|SS_List $value
*/
public function __construct($name, $title = '', $source = array(), $value = array()) {
parent::__construct($name, $title, $source, $value);
}
/**
* @return bool
*/
public function getShouldLazyLoad() {
return $this->shouldLazyLoad;
}
/**
* @param bool $shouldLazyLoad
*
* @return static
*/
public function setShouldLazyLoad($shouldLazyLoad) {
$this->shouldLazyLoad = $shouldLazyLoad;
return $this;
}
/**
* @return int
*/
public function getLazyLoadItemLimit() {
return $this->lazyLoadItemLimit;
}
/**
* @param int $lazyLoadItemLimit
*
* @return static
*/
public function setLazyLoadItemLimit($lazyLoadItemLimit) {
$this->lazyLoadItemLimit = $lazyLoadItemLimit;
return $this;
}
/** /**
* @return bool * @var bool
*/ */
public function getIsMultiple() { protected $shouldLazyLoad = false;
return $this->isMultiple;
}
/** /**
* @param bool $isMultiple * @var int
* */
* @return static protected $lazyLoadItemLimit = 10;
*/
public function setIsMultiple($isMultiple) {
$this->isMultiple = $isMultiple;
return $this; /**
} * @var null|DataObject
*/
protected $record;
/** /**
* @return null|DataObject * @var bool
*/ */
public function getRecord() { protected $isMultiple = true;
if($this->record) {
return $this->record;
}
if($form = $this->getForm()) { /**
return $form->getRecord(); * @param string $name
} * @param string $title
* @param array|SS_List $source
* @param array|SS_List $value
*/
public function __construct($name, $title = '', $source = array(), $value = array())
{
parent::__construct($name, $title, $source, $value);
}
return null; /**
} * @return bool
*/
public function getShouldLazyLoad()
{
return $this->shouldLazyLoad;
}
/** /**
* @param DataObject $record * @param bool $shouldLazyLoad
* *
* @return $this * @return static
*/ */
public function setRecord(DataObject $record) { public function setShouldLazyLoad($shouldLazyLoad)
$this->record = $record; {
$this->shouldLazyLoad = $shouldLazyLoad;
return $this; return $this;
} }
/** /**
* {@inheritdoc} * @return int
*/ */
public function Field($properties = array()) { public function getLazyLoadItemLimit()
Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css'); {
Requirements::css(TAG_FIELD_DIR . '/css/TagField.css'); return $this->lazyLoadItemLimit;
}
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); /**
Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js'); * @param int $lazyLoadItemLimit
Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js'); *
Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js'); * @return static
*/
public function setLazyLoadItemLimit($lazyLoadItemLimit)
{
$this->lazyLoadItemLimit = $lazyLoadItemLimit;
$this->addExtraClass('ss-tag-field'); return $this;
}
if ($this->getIsMultiple()) { /**
$this->setAttribute('multiple', 'multiple'); * @return bool
*/
public function getIsMultiple()
{
return $this->isMultiple;
}
/**
* @param bool $isMultiple
*
* @return static
*/
public function setIsMultiple($isMultiple)
{
$this->isMultiple = $isMultiple;
return $this;
}
/**
* @return null|DataObject
*/
public function getRecord()
{
if ($this->record) {
return $this->record;
} }
if($this->getShouldLazyLoad()) { if ($form = $this->getForm()) {
$this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL()); return $form->getRecord();
} else { }
$properties = array_merge($properties, array(
'Options' => $this->getOptions()
));
}
return $this return null;
->customise($properties) }
->renderWith(array("templates/TagField"));
}
/** /**
* @return string * @param DataObject $record
*/ *
protected function getSuggestURL() { * @return $this
return Controller::join_links($this->Link(), 'suggest'); */
} public function setRecord(DataObject $record)
{
$this->record = $record;
/** return $this;
* @return ArrayList }
*/
protected function getOptions() {
$options = ArrayList::create();
$source = $this->getSource(); /**
* {@inheritdoc}
*/
public function Field($properties = array())
{
Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
if($source instanceof Iterator) { Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
$source = iterator_to_array($source); Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
} Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
$values = $this->Value(); $this->addExtraClass('ss-tag-field');
foreach($source as $value) { if ($this->getIsMultiple()) {
$options->push( $this->setAttribute('multiple', 'multiple');
ArrayData::create(array( }
'Title' => $value,
'Value' => $value,
'Selected' => in_array($value, $values),
))
);
}
return $options; if ($this->getShouldLazyLoad()) {
} $this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
} else {
$properties = array_merge($properties, array(
'Options' => $this->getOptions()
));
}
/** return $this
* {@inheritdoc} ->customise($properties)
*/ ->renderWith(array("templates/TagField"));
public function setValue($value, $source = null) { }
if(is_string($value)) {
$value = explode(',', $value);
}
if($source instanceof DataObject) { /**
$name = $this->getName(); * @return string
$value = explode(',', $source->$name); */
} protected function getSuggestURL()
{
return Controller::join_links($this->Link(), 'suggest');
}
if($source instanceof SS_List) { /**
$value = $source->column('ID'); * @return ArrayList
} */
protected function getOptions()
{
$options = ArrayList::create();
return parent::setValue(array_filter($value)); $source = $this->getSource();
}
/** if ($source instanceof Iterator) {
* {@inheritdoc} $source = iterator_to_array($source);
*/ }
public function getAttributes() {
return array_merge(
parent::getAttributes(),
array('name' => $this->getName() . '[]')
);
}
/** $values = $this->Value();
* {@inheritdoc}
*/
public function saveInto(DataObjectInterface $record) {
parent::saveInto($record);
$name = $this->getName(); foreach ($source as $value) {
$options->push(
ArrayData::create(array(
'Title' => $value,
'Value' => $value,
'Selected' => in_array($value, $values),
))
);
}
$record->$name = join(',', $this->Value()); return $options;
$record->write(); }
}
/** /**
* Returns a JSON string of tags, for lazy loading. * {@inheritdoc}
* */
* @param SS_HTTPRequest $request public function setValue($value, $source = null)
* {
* @return SS_HTTPResponse if (is_string($value)) {
*/ $value = explode(',', $value);
public function suggest(SS_HTTPRequest $request) { }
$responseBody = Convert::raw2json(
array('items' => array())
);
$response = new SS_HTTPResponse(); if ($source instanceof DataObject) {
$response->addHeader('Content-Type', 'application/json'); $name = $this->getName();
$value = explode(',', $source->$name);
}
if($record = $this->getRecord()) { if ($source instanceof SS_List) {
$tags = array(); $value = $source->column('ID');
$term = $request->getVar('term'); }
if($record->hasField($this->getName())) { return parent::setValue(array_filter($value));
$tags = $this->getTags($term); }
}
$responseBody = Convert::raw2json( /**
array('items' => $tags) * {@inheritdoc}
); */
} public function getAttributes()
{
return array_merge(
parent::getAttributes(),
array('name' => $this->getName() . '[]')
);
}
$response->setBody($responseBody); /**
* {@inheritdoc}
*/
public function saveInto(DataObjectInterface $record)
{
parent::saveInto($record);
return $response; $name = $this->getName();
}
/** $record->$name = join(',', $this->Value());
* Returns array of arrays representing tags. $record->write();
* }
* @param string $term
*
* @return array
*/
protected function getTags($term) {
$record = $this->getRecord();
if(!$record) { /**
return array(); * Returns a JSON string of tags, for lazy loading.
} *
* @param SS_HTTPRequest $request
*
* @return SS_HTTPResponse
*/
public function suggest(SS_HTTPRequest $request)
{
$responseBody = Convert::raw2json(
array('items' => array())
);
$fieldName = $this->getName(); $response = new SS_HTTPResponse();
$className = $record->getClassName(); $response->addHeader('Content-Type', 'application/json');
$term = Convert::raw2sql($term); if ($record = $this->getRecord()) {
$tags = array();
$term = $request->getVar('term');
$query = $className::get() if ($record->hasField($this->getName())) {
->filter($fieldName . ':PartialMatch:nocase', $term) $tags = $this->getTags($term);
->limit($this->getLazyLoadItemLimit()); }
$items = array(); $responseBody = Convert::raw2json(
array('items' => $tags)
);
}
foreach($query->column($fieldName) as $tags) { $response->setBody($responseBody);
$tags = explode(',', $tags);
foreach($tags as $i => $tag) { return $response;
if(stripos($tag, $term) !== false && !in_array($tag, $items)) { }
$items[] = array(
'id' => $tag,
'text' => $tag
);
}
}
}
return $items; /**
} * Returns array of arrays representing tags.
*
* @param string $term
*
* @return array
*/
protected function getTags($term)
{
$record = $this->getRecord();
/** if (!$record) {
* DropdownField assumes value will be a scalar so we must return array();
* override validate. This only applies to Silverstripe 3.2+ }
*
* @param Validator $validator
* @return bool
*/
public function validate($validator) {
return true;
}
$fieldName = $this->getName();
$className = $record->getClassName();
$term = Convert::raw2sql($term);
$query = $className::get()
->filter($fieldName . ':PartialMatch:nocase', $term)
->limit($this->getLazyLoadItemLimit());
$items = array();
foreach ($query->column($fieldName) as $tags) {
$tags = explode(',', $tags);
foreach ($tags as $i => $tag) {
if (stripos($tag, $term) !== false && !in_array($tag, $items)) {
$items[] = array(
'id' => $tag,
'text' => $tag
);
}
}
}
return $items;
}
/**
* DropdownField assumes value will be a scalar so we must
* override validate. This only applies to Silverstripe 3.2+
*
* @param Validator $validator
* @return bool
*/
public function validate($validator)
{
return true;
}
} }

View File

@ -6,382 +6,403 @@
* @package forms * @package forms
* @subpackage fields * @subpackage fields
*/ */
class TagField extends DropdownField { class TagField extends DropdownField
/** {
* @var array /**
*/ * @var array
public static $allowed_actions = array( */
'suggest', public static $allowed_actions = array(
); 'suggest',
);
/**
* @var bool
*/
protected $shouldLazyLoad = false;
/**
* @var int
*/
protected $lazyLoadItemLimit = 10;
/**
* @var bool
*/
protected $canCreate = true;
/**
* @var string
*/
protected $titleField = 'Title';
/**
* @var bool
*/
protected $isMultiple = true;
/**
* @param string $name
* @param string $title
* @param null|DataList $source
* @param null|DataList $value
*/
public function __construct($name, $title = '', $source = null, $value = null) {
parent::__construct($name, $title, $source, $value);
}
/**
* @return bool
*/
public function getShouldLazyLoad() {
return $this->shouldLazyLoad;
}
/**
* @param bool $shouldLazyLoad
*
* @return static
*/
public function setShouldLazyLoad($shouldLazyLoad) {
$this->shouldLazyLoad = $shouldLazyLoad;
return $this;
}
/**
* @return int
*/
public function getLazyLoadItemLimit() {
return $this->lazyLoadItemLimit;
}
/**
* @param int $lazyLoadItemLimit
*
* @return static
*/
public function setLazyLoadItemLimit($lazyLoadItemLimit) {
$this->lazyLoadItemLimit = $lazyLoadItemLimit;
return $this;
}
/** /**
* @return bool * @var bool
*/ */
public function getIsMultiple() { protected $shouldLazyLoad = false;
return $this->isMultiple;
}
/** /**
* @param bool $isMultiple * @var int
* */
* @return static protected $lazyLoadItemLimit = 10;
*/
public function setIsMultiple($isMultiple) {
$this->isMultiple = $isMultiple;
return $this; /**
} * @var bool
*/
protected $canCreate = true;
/** /**
* @return bool * @var string
*/ */
public function getCanCreate() { protected $titleField = 'Title';
return $this->canCreate;
}
/** /**
* @param bool $canCreate * @var bool
* */
* @return static protected $isMultiple = true;
*/
public function setCanCreate($canCreate) {
$this->canCreate = $canCreate;
return $this; /**
} * @param string $name
* @param string $title
* @param null|DataList $source
* @param null|DataList $value
*/
public function __construct($name, $title = '', $source = null, $value = null)
{
parent::__construct($name, $title, $source, $value);
}
/** /**
* @return string * @return bool
*/ */
public function getTitleField() { public function getShouldLazyLoad()
return $this->titleField; {
} return $this->shouldLazyLoad;
}
/** /**
* @param string $titleField * @param bool $shouldLazyLoad
* *
* @return $this * @return static
*/ */
public function setTitleField($titleField) { public function setShouldLazyLoad($shouldLazyLoad)
$this->titleField = $titleField; {
$this->shouldLazyLoad = $shouldLazyLoad;
return $this; return $this;
} }
/** /**
* {@inheritdoc} * @return int
*/ */
public function Field($properties = array()) { public function getLazyLoadItemLimit()
Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css'); {
Requirements::css(TAG_FIELD_DIR . '/css/TagField.css'); return $this->lazyLoadItemLimit;
}
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js'); /**
Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js'); * @param int $lazyLoadItemLimit
Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js'); *
Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js'); * @return static
*/
public function setLazyLoadItemLimit($lazyLoadItemLimit)
{
$this->lazyLoadItemLimit = $lazyLoadItemLimit;
$this->addExtraClass('ss-tag-field'); return $this;
}
/**
* @return bool
*/
public function getIsMultiple()
{
return $this->isMultiple;
}
/**
* @param bool $isMultiple
*
* @return static
*/
public function setIsMultiple($isMultiple)
{
$this->isMultiple = $isMultiple;
return $this;
}
/**
* @return bool
*/
public function getCanCreate()
{
return $this->canCreate;
}
/**
* @param bool $canCreate
*
* @return static
*/
public function setCanCreate($canCreate)
{
$this->canCreate = $canCreate;
return $this;
}
/**
* @return string
*/
public function getTitleField()
{
return $this->titleField;
}
/**
* @param string $titleField
*
* @return $this
*/
public function setTitleField($titleField)
{
$this->titleField = $titleField;
return $this;
}
/**
* {@inheritdoc}
*/
public function Field($properties = array())
{
Requirements::css(TAG_FIELD_DIR . '/css/select2.min.css');
Requirements::css(TAG_FIELD_DIR . '/css/TagField.css');
Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
Requirements::javascript(THIRDPARTY_DIR . '/jquery-entwine/dist/jquery.entwine-dist.js');
Requirements::javascript(TAG_FIELD_DIR . '/js/select2.js');
Requirements::javascript(TAG_FIELD_DIR . '/js/TagField.js');
$this->addExtraClass('ss-tag-field');
if ($this->getIsMultiple()) { if ($this->getIsMultiple()) {
$this->setAttribute('multiple', 'multiple'); $this->setAttribute('multiple', 'multiple');
} }
if($this->shouldLazyLoad) { if ($this->shouldLazyLoad) {
$this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL()); $this->setAttribute('data-ss-tag-field-suggest-url', $this->getSuggestURL());
} else { } else {
$properties = array_merge($properties, array( $properties = array_merge($properties, array(
'Options' => $this->getOptions() 'Options' => $this->getOptions()
)); ));
} }
return $this return $this
->customise($properties) ->customise($properties)
->renderWith(array("templates/TagField")); ->renderWith(array("templates/TagField"));
} }
/** /**
* @return string * @return string
*/ */
protected function getSuggestURL() { protected function getSuggestURL()
return Controller::join_links($this->Link(), 'suggest'); {
} return Controller::join_links($this->Link(), 'suggest');
}
/** /**
* @return ArrayList * @return ArrayList
*/ */
protected function getOptions() { protected function getOptions()
$options = ArrayList::create(); {
$options = ArrayList::create();
$source = $this->getSource(); $source = $this->getSource();
if(!$source) { if (!$source) {
$source = new ArrayList(); $source = new ArrayList();
} }
$dataClass = $source->dataClass(); $dataClass = $source->dataClass();
$values = $this->Value(); $values = $this->Value();
if(!$values) { if (!$values) {
return $options; return $options;
} }
if(is_array($values)) { if (is_array($values)) {
$values = DataList::create($dataClass)->filter('ID', $values); $values = DataList::create($dataClass)->filter('ID', $values);
} }
$ids = $values->column('ID'); $ids = $values->column('ID');
$titleField = $this->getTitleField(); $titleField = $this->getTitleField();
foreach($source as $object) { foreach ($source as $object) {
$options->push( $options->push(
ArrayData::create(array( ArrayData::create(array(
'Title' => $object->$titleField, 'Title' => $object->$titleField,
'Value' => $object->ID, 'Value' => $object->ID,
'Selected' => in_array($object->ID, $ids), 'Selected' => in_array($object->ID, $ids),
)) ))
); );
} }
return $options; return $options;
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function setValue($value, $source = null) { public function setValue($value, $source = null)
if($source instanceof DataObject) { {
$name = $this->getName(); if ($source instanceof DataObject) {
$name = $this->getName();
if($source->hasMethod($name)) { if ($source->hasMethod($name)) {
$value = $source->$name()->getIDList(); $value = $source->$name()->getIDList();
} }
} elseif($value instanceof SS_List) { } elseif ($value instanceof SS_List) {
$value = $value->column('ID'); $value = $value->column('ID');
} }
if(!is_array($value)) { if (!is_array($value)) {
return parent::setValue($value); return parent::setValue($value);
} }
return parent::setValue(array_filter($value)); return parent::setValue(array_filter($value));
} }
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getAttributes() { public function getAttributes()
return array_merge( {
parent::getAttributes(), return array_merge(
array('name' => $this->getName() . '[]') parent::getAttributes(),
); array('name' => $this->getName() . '[]')
} );
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function saveInto(DataObjectInterface $record) { public function saveInto(DataObjectInterface $record)
parent::saveInto($record); {
parent::saveInto($record);
$name = $this->getName(); $name = $this->getName();
$titleField = $this->getTitleField(); $titleField = $this->getTitleField();
$source = $this->getSource(); $source = $this->getSource();
$values = $this->Value(); $values = $this->Value();
if(!$values) { if (!$values) {
$values = array(); $values = array();
} }
if(empty($record) || empty($source) || empty($titleField)) { if (empty($record) || empty($source) || empty($titleField)) {
return; return;
} }
if(!$record->hasMethod($name)) { if (!$record->hasMethod($name)) {
throw new Exception( throw new Exception(
sprintf("%s does not have a %s method", get_class($record), $name) sprintf("%s does not have a %s method", get_class($record), $name)
); );
} }
$relation = $record->$name(); $relation = $record->$name();
foreach($values as $i => $value) { foreach ($values as $i => $value) {
if(!is_numeric($value)) { if (!is_numeric($value)) {
if(!$this->getCanCreate()) { if (!$this->getCanCreate()) {
unset($values[$i]); unset($values[$i]);
continue; continue;
} }
// Get or create record // Get or create record
$record = $this->getOrCreateTag($value); $record = $this->getOrCreateTag($value);
$values[$i] = $record->ID; $values[$i] = $record->ID;
} }
} }
if($values instanceof SS_List) { if ($values instanceof SS_List) {
$values = iterator_to_array($values); $values = iterator_to_array($values);
} }
$relation->setByIDList(array_filter($values)); $relation->setByIDList(array_filter($values));
} }
/** /**
* Get or create tag with the given value * Get or create tag with the given value
* *
* @param string $term * @param string $term
* @return DataObject * @return DataObject
*/ */
protected function getOrCreateTag($term) { protected function getOrCreateTag($term)
// Check if existing record can be found {
$source = $this->getSource(); // Check if existing record can be found
$titleField = $this->getTitleField(); $source = $this->getSource();
$record = $source $titleField = $this->getTitleField();
->filter($titleField, $term) $record = $source
->first(); ->filter($titleField, $term)
if($record) { ->first();
return $record; if ($record) {
} return $record;
}
// Create new instance if not yet saved // Create new instance if not yet saved
$dataClass = $source->dataClass(); $dataClass = $source->dataClass();
$record = Injector::inst()->create($dataClass); $record = Injector::inst()->create($dataClass);
$record->{$titleField} = $term; $record->{$titleField} = $term;
$record->write(); $record->write();
return $record; return $record;
} }
/** /**
* Returns a JSON string of tags, for lazy loading. * Returns a JSON string of tags, for lazy loading.
* *
* @param SS_HTTPRequest $request * @param SS_HTTPRequest $request
* *
* @return SS_HTTPResponse * @return SS_HTTPResponse
*/ */
public function suggest(SS_HTTPRequest $request) { public function suggest(SS_HTTPRequest $request)
$tags = $this->getTags($request->getVar('term')); {
$tags = $this->getTags($request->getVar('term'));
$response = new SS_HTTPResponse(); $response = new SS_HTTPResponse();
$response->addHeader('Content-Type', 'application/json'); $response->addHeader('Content-Type', 'application/json');
$response->setBody(json_encode(array('items' => $tags))); $response->setBody(json_encode(array('items' => $tags)));
return $response; return $response;
} }
/** /**
* Returns array of arrays representing tags. * Returns array of arrays representing tags.
* *
* @param string $term * @param string $term
* *
* @return array * @return array
*/ */
protected function getTags($term) { protected function getTags($term)
/** {
* @var DataList $source /**
*/ * @var DataList $source
$source = $this->getSource(); */
$source = $this->getSource();
$titleField = $this->getTitleField(); $titleField = $this->getTitleField();
$query = $source $query = $source
->filter($titleField . ':PartialMatch:nocase', $term) ->filter($titleField . ':PartialMatch:nocase', $term)
->sort($titleField) ->sort($titleField)
->limit($this->getLazyLoadItemLimit()); ->limit($this->getLazyLoadItemLimit());
// Map into a distinct list // Map into a distinct list
$items = array(); $items = array();
$titleField = $this->getTitleField(); $titleField = $this->getTitleField();
foreach($query->map('ID', $titleField) as $id => $title) { foreach ($query->map('ID', $titleField) as $id => $title) {
$items[$title] = array( $items[$title] = array(
'id' => $id, 'id' => $id,
'text' => $title 'text' => $title
); );
} }
return array_values($items); return array_values($items);
} }
/**
* DropdownField assumes value will be a scalar so we must
* override validate. This only applies to Silverstripe 3.2+
*
* @param Validator $validator
* @return bool
*/
public function validate($validator) {
return true;
}
/**
* DropdownField assumes value will be a scalar so we must
* override validate. This only applies to Silverstripe 3.2+
*
* @param Validator $validator
* @return bool
*/
public function validate($validator)
{
return true;
}
} }

View File

@ -3,147 +3,157 @@
/** /**
* @mixin PHPUnit_Framework_TestCase * @mixin PHPUnit_Framework_TestCase
*/ */
class StringTagFieldTest extends SapphireTest { class StringTagFieldTest extends SapphireTest
/** {
* @var string /**
*/ * @var string
public static $fixture_file = 'tagfield/tests/StringTagFieldTest.yml'; */
public static $fixture_file = 'tagfield/tests/StringTagFieldTest.yml';
/** /**
* @var array * @var array
*/ */
protected $extraDataObjects = array( protected $extraDataObjects = array(
'StringTagFieldTestBlogPost', 'StringTagFieldTestBlogPost',
); );
function testItSavesTagsOnNewRecords() { public function testItSavesTagsOnNewRecords()
$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1'); {
$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
$field = new StringTagField('Tags'); $field = new StringTagField('Tags');
$field->setValue(array('Tag1', 'Tag2')); $field->setValue(array('Tag1', 'Tag2'));
$field->saveInto($record); $field->saveInto($record);
$record->write(); $record->write();
$this->assertEquals('Tag1,Tag2', $record->Tags); $this->assertEquals('Tag1,Tag2', $record->Tags);
} }
/** /**
* @param string $name * @param string $name
* *
* @return StringTagFieldTestBlogPost * @return StringTagFieldTestBlogPost
*/ */
protected function getNewStringTagFieldTestBlogPost($name) { protected function getNewStringTagFieldTestBlogPost($name)
return $this->objFromFixture( {
'StringTagFieldTestBlogPost', return $this->objFromFixture(
$name 'StringTagFieldTestBlogPost',
); $name
} );
}
function testItSavesTagsOnExistingRecords() { public function testItSavesTagsOnExistingRecords()
$record = $this->getNewStringTagFieldTestBlogPost('BlogPost1'); {
$record->write(); $record = $this->getNewStringTagFieldTestBlogPost('BlogPost1');
$record->write();
$field = new StringTagField('Tags'); $field = new StringTagField('Tags');
$field->setValue(array('Tag1', 'Tag2')); $field->setValue(array('Tag1', 'Tag2'));
$field->saveInto($record); $field->saveInto($record);
$this->assertEquals('Tag1,Tag2', $record->Tags); $this->assertEquals('Tag1,Tag2', $record->Tags);
} }
function testItSuggestsTags() { public function testItSuggestsTags()
$record = $this->getNewStringTagFieldTestBlogPost('BlogPost2'); {
$record = $this->getNewStringTagFieldTestBlogPost('BlogPost2');
$field = new StringTagField('Tags'); $field = new StringTagField('Tags');
$field->setRecord($record); $field->setRecord($record);
/** /**
* Partial tag title match. * Partial tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag')); $request = $this->getNewRequest(array('term' => 'Tag'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}', '{"items":[{"id":"Tag1","text":"Tag1"},{"id":"Tag2","text":"Tag2"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* Exact tag title match. * Exact tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag1')); $request = $this->getNewRequest(array('term' => 'Tag1'));
$this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}'); $this->assertEquals($field->suggest($request)->getBody(), '{"items":[{"id":"Tag1","text":"Tag1"}]}');
/** /**
* Case-insensitive tag title match. * Case-insensitive tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'TAG1')); $request = $this->getNewRequest(array('term' => 'TAG1'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":"Tag1","text":"Tag1"}]}', '{"items":[{"id":"Tag1","text":"Tag1"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* No tag title match. * No tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'unknown')); $request = $this->getNewRequest(array('term' => 'unknown'));
$this->assertEquals( $this->assertEquals(
'{"items":[]}', '{"items":[]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
} }
/** /**
* @param array $parameters * @param array $parameters
* *
* @return SS_HTTPRequest * @return SS_HTTPRequest
*/ */
protected function getNewRequest(array $parameters) { protected function getNewRequest(array $parameters)
return new SS_HTTPRequest( {
'get', return new SS_HTTPRequest(
'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest', 'get',
$parameters 'StringTagFieldTestController/StringTagFieldTestForm/fields/Tags/suggest',
); $parameters
} );
}
} }
/** /**
* @property string $Tags * @property string $Tags
*/ */
class StringTagFieldTestBlogPost extends DataObject implements TestOnly { class StringTagFieldTestBlogPost extends DataObject implements TestOnly
/** {
* @var array /**
*/ * @var array
private static $db = array( */
'Title' => 'Text', private static $db = array(
'Content' => 'Text', 'Title' => 'Text',
'Tags' => 'Text', 'Content' => 'Text',
); 'Tags' => 'Text',
);
} }
class StringTagFieldTestController extends Controller implements TestOnly { class StringTagFieldTestController extends Controller implements TestOnly
/** {
* @return Form /**
*/ * @return Form
public function StringTagFieldTestForm() { */
$fields = new FieldList( public function StringTagFieldTestForm()
$tagField = new StringTagField('Tags') {
); $fields = new FieldList(
$tagField = new StringTagField('Tags')
);
$actions = new FieldList( $actions = new FieldList(
new FormAction('StringTagFieldTestFormSubmit') new FormAction('StringTagFieldTestFormSubmit')
); );
return new Form($this, 'StringTagFieldTestForm', $fields, $actions); return new Form($this, 'StringTagFieldTestForm', $fields, $actions);
} }
/** /**
* @param DataObject $dataObject * @param DataObject $dataObject
* @param Form $form * @param Form $form
*/ */
public function StringTagFieldTestFormSubmit(DataObject $dataObject, Form $form) { public function StringTagFieldTestFormSubmit(DataObject $dataObject, Form $form)
$form->saveInto($dataObject); {
} $form->saveInto($dataObject);
}
} }

View File

@ -3,353 +3,372 @@
/** /**
* @mixin PHPUnit_Framework_TestCase * @mixin PHPUnit_Framework_TestCase
*/ */
class TagFieldTest extends SapphireTest { class TagFieldTest extends SapphireTest
/** {
* @var string /**
*/ * @var string
public static $fixture_file = 'tagfield/tests/TagFieldTest.yml'; */
public static $fixture_file = 'tagfield/tests/TagFieldTest.yml';
/** /**
* @var array * @var array
*/ */
protected $extraDataObjects = array( protected $extraDataObjects = array(
'TagFieldTestBlogTag', 'TagFieldTestBlogTag',
'TagFieldTestBlogPost', 'TagFieldTestBlogPost',
); );
function testItSavesLinksToNewTagsOnNewRecords() { public function testItSavesLinksToNewTagsOnNewRecords()
$record = $this->getNewTagFieldTestBlogPost('BlogPost1'); {
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
$field->setValue(array('Tag3', 'Tag4')); $field->setValue(array('Tag3', 'Tag4'));
$field->saveInto($record); $field->saveInto($record);
$record->write(); $record->write();
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag3', 'Tag4'), array('Tag3', 'Tag4'),
$record $record
); );
} }
/** /**
* @param string $name * @param string $name
* *
* @return TagFieldTestBlogPost * @return TagFieldTestBlogPost
*/ */
protected function getNewTagFieldTestBlogPost($name) { protected function getNewTagFieldTestBlogPost($name)
return $this->objFromFixture( {
'TagFieldTestBlogPost', return $this->objFromFixture(
$name 'TagFieldTestBlogPost',
); $name
} );
}
/** /**
* @param array $expected * @param array $expected
* @param TagFieldTestBlogPost $record * @param TagFieldTestBlogPost $record
*/ */
protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record) { protected function compareExpectedAndActualTags(array $expected, TagFieldTestBlogPost $record)
$this->compareTagLists($expected, $record->Tags()); {
} $this->compareTagLists($expected, $record->Tags());
}
/** /**
* Ensure a source of tags matches the given string tag names * Ensure a source of tags matches the given string tag names
* *
* @param array $expected * @param array $expected
* @param DataList $actualSource * @param DataList $actualSource
*/ */
protected function compareTagLists(array $expected, DataList $actualSource) { protected function compareTagLists(array $expected, DataList $actualSource)
$actual = array_values($actualSource->map('ID', 'Title')->toArray()); {
$actual = array_values($actualSource->map('ID', 'Title')->toArray());
sort($expected); sort($expected);
sort($actual); sort($actual);
$this->assertEquals( $this->assertEquals(
$expected, $expected,
$actual $actual
); );
} }
public function testItSavesLinksToNewTagsOnExistingRecords() { public function testItSavesLinksToNewTagsOnExistingRecords()
$record = $this->getNewTagFieldTestBlogPost('BlogPost1'); {
$record->write(); $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
$record->write();
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
$field->setValue(array('Tag3', 'Tag4')); $field->setValue(array('Tag3', 'Tag4'));
$field->saveInto($record); $field->saveInto($record);
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag3', 'Tag4'), array('Tag3', 'Tag4'),
$record $record
); );
} }
public function testItSavesLinksToExistingTagsOnNewRecords() { public function testItSavesLinksToExistingTagsOnNewRecords()
$record = $this->getNewTagFieldTestBlogPost('BlogPost1'); {
$record = $this->getNewTagFieldTestBlogPost('BlogPost1');
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
$field->setValue(array('Tag1', 'Tag2')); $field->setValue(array('Tag1', 'Tag2'));
$field->saveInto($record); $field->saveInto($record);
$record->write(); $record->write();
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag1', 'Tag2'), array('Tag1', 'Tag2'),
$record $record
); );
} }
public function testItSavesLinksToExistingTagsOnExistingRecords() { public function testItSavesLinksToExistingTagsOnExistingRecords()
$record = $this->getNewTagFieldTestBlogPost('BlogPost1'); {
$record->write(); $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
$record->write();
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
$field->setValue(array('Tag1', 'Tag2')); $field->setValue(array('Tag1', 'Tag2'));
$field->saveInto($record); $field->saveInto($record);
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag1', 'Tag2'), array('Tag1', 'Tag2'),
$record $record
); );
} }
/** /**
* Ensure that {@see TagField::saveInto} respects existing tags * Ensure that {@see TagField::saveInto} respects existing tags
*/ */
public function testSaveDuplicateTags() { public function testSaveDuplicateTags()
$record = $this->getNewTagFieldTestBlogPost('BlogPost2'); {
$record->write(); $record = $this->getNewTagFieldTestBlogPost('BlogPost2');
$tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2'); $record->write();
$tag2ID = $this->idFromFixture('TagFieldTestBlogTag', 'Tag2');
// Check tags before write // Check tags before write
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag1', 'Tag2'), array('Tag1', 'Tag2'),
$record $record
); );
$this->compareTagLists( $this->compareTagLists(
array('Tag1', 'Tag2'), array('Tag1', 'Tag2'),
TagFieldTestBlogTag::get() TagFieldTestBlogTag::get()
); );
$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID')); $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
// Write new tags // Write new tags
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
$field->setValue(array('Tag2', 'Tag3')); $field->setValue(array('Tag2', 'Tag3'));
$field->saveInto($record); $field->saveInto($record);
// Check only one new tag was added // Check only one new tag was added
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag2', 'Tag3'), array('Tag2', 'Tag3'),
$record $record
); );
// Ensure that only one new dataobject was added and that tag2s id has not changed // Ensure that only one new dataobject was added and that tag2s id has not changed
$this->compareTagLists( $this->compareTagLists(
array('Tag1', 'Tag2', 'Tag3'), array('Tag1', 'Tag2', 'Tag3'),
TagFieldTestBlogTag::get() TagFieldTestBlogTag::get()
); );
$this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID')); $this->assertContains($tag2ID, TagFieldTestBlogTag::get()->column('ID'));
} }
function testItSuggestsTags() { public function testItSuggestsTags()
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')); {
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'));
/** /**
* Partial tag title match. * Partial tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag')); $request = $this->getNewRequest(array('term' => 'Tag'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":1,"text":"Tag1"},{"id":2,"text":"Tag2"}]}', '{"items":[{"id":1,"text":"Tag1"},{"id":2,"text":"Tag2"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* Exact tag title match. * Exact tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag1')); $request = $this->getNewRequest(array('term' => 'Tag1'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":1,"text":"Tag1"}]}', '{"items":[{"id":1,"text":"Tag1"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* Case-insensitive tag title match. * Case-insensitive tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'TAG1')); $request = $this->getNewRequest(array('term' => 'TAG1'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":1,"text":"Tag1"}]}', '{"items":[{"id":1,"text":"Tag1"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* No tag title match. * No tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'unknown')); $request = $this->getNewRequest(array('term' => 'unknown'));
$this->assertEquals( $this->assertEquals(
'{"items":[]}', '{"items":[]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
} }
/** /**
* Tests that TagField supports pre-filtered data sources * Tests that TagField supports pre-filtered data sources
*/ */
public function testRestrictedSuggestions() { public function testRestrictedSuggestions()
$source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2'); {
$field = new TagField('Tags', '', $source); $source = TagFieldTestBlogTag::get()->exclude('Title', 'Tag2');
$field = new TagField('Tags', '', $source);
/** /**
* Partial tag title match. * Partial tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag')); $request = $this->getNewRequest(array('term' => 'Tag'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":1,"text":"Tag1"}]}', '{"items":[{"id":1,"text":"Tag1"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* Exact tag title match. * Exact tag title match.
*/ */
$request = $this->getNewRequest(array('term' => 'Tag1')); $request = $this->getNewRequest(array('term' => 'Tag1'));
$this->assertEquals( $this->assertEquals(
'{"items":[{"id":1,"text":"Tag1"}]}', '{"items":[{"id":1,"text":"Tag1"}]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
/** /**
* Excluded item doesn't appear in matches * Excluded item doesn't appear in matches
*/ */
$request = $this->getNewRequest(array('term' => 'Tag2')); $request = $this->getNewRequest(array('term' => 'Tag2'));
$this->assertEquals( $this->assertEquals(
'{"items":[]}', '{"items":[]}',
$field->suggest($request)->getBody() $field->suggest($request)->getBody()
); );
} }
/** /**
* @param array $parameters * @param array $parameters
* *
* @return SS_HTTPRequest * @return SS_HTTPRequest
*/ */
protected function getNewRequest(array $parameters) { protected function getNewRequest(array $parameters)
return new SS_HTTPRequest( {
'get', return new SS_HTTPRequest(
'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest', 'get',
$parameters 'TagFieldTestController/TagFieldTestForm/fields/Tags/suggest',
); $parameters
} );
}
function testItDisplaysValuesFromRelations() { public function testItDisplaysValuesFromRelations()
$record = $this->getNewTagFieldTestBlogPost('BlogPost1'); {
$record->write(); $record = $this->getNewTagFieldTestBlogPost('BlogPost1');
$record->write();
$form = new Form( $form = new Form(
new TagFieldTestController($record), new TagFieldTestController($record),
'Form', 'Form',
new FieldList( new FieldList(
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')) $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
), ),
new FieldList() new FieldList()
); );
$form->loadDataFrom( $form->loadDataFrom(
$this->objFromFixture('TagFieldTestBlogPost', 'BlogPost2') $this->objFromFixture('TagFieldTestBlogPost', 'BlogPost2')
); );
$this->assertEquals($field->Value(), array(1 => 1, 2 => 2)); $this->assertEquals($field->Value(), array(1 => 1, 2 => 2));
} }
function testItIgnoresNewTagsIfCannotCreate() { public function testItIgnoresNewTagsIfCannotCreate()
$record = new TagFieldTestBlogPost(); {
$record->write(); $record = new TagFieldTestBlogPost();
$record->write();
$tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first(); $tag = TagFieldTestBlogTag::get()->filter('Title', 'Tag1')->first();
$field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'), array($tag->ID, 'Tag3')); $field = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'), array($tag->ID, 'Tag3'));
$field->setCanCreate(false); $field->setCanCreate(false);
$field->saveInto($record); $field->saveInto($record);
/** /**
* @var TagFieldTestBlogPost $record * @var TagFieldTestBlogPost $record
*/ */
$record = DataObject::get_by_id('TagFieldTestBlogPost', $record->ID); $record = DataObject::get_by_id('TagFieldTestBlogPost', $record->ID);
$this->compareExpectedAndActualTags( $this->compareExpectedAndActualTags(
array('Tag1'), array('Tag1'),
$record $record
); );
} }
} }
class TagFieldTestBlogTag extends DataObject implements TestOnly { class TagFieldTestBlogTag extends DataObject implements TestOnly
/** {
* @var string /**
*/ * @var string
private static $default_sort = '"TagFieldTestBlogTag"."ID" ASC'; */
private static $default_sort = '"TagFieldTestBlogTag"."ID" ASC';
/** /**
* @var array * @var array
*/ */
private static $db = array( private static $db = array(
'Title' => 'Varchar(200)', 'Title' => 'Varchar(200)',
); );
/** /**
* @var array * @var array
*/ */
private static $belongs_many_many = array( private static $belongs_many_many = array(
'BlogPosts' => 'TagFieldTestBlogPost', 'BlogPosts' => 'TagFieldTestBlogPost',
); );
} }
/** /**
* @method ManyManyList Tags() * @method ManyManyList Tags()
*/ */
class TagFieldTestBlogPost extends DataObject implements TestOnly { class TagFieldTestBlogPost extends DataObject implements TestOnly
/** {
* @var array /**
*/ * @var array
private static $db = array( */
'Title' => 'Text', private static $db = array(
'Content' => 'Text', 'Title' => 'Text',
); 'Content' => 'Text',
);
/** /**
* @var array * @var array
*/ */
private static $many_many = array( private static $many_many = array(
'Tags' => 'TagFieldTestBlogTag', 'Tags' => 'TagFieldTestBlogTag',
); );
} }
class TagFieldTestController extends Controller implements TestOnly { class TagFieldTestController extends Controller implements TestOnly
/** {
* @return Form /**
*/ * @return Form
public function TagFieldTestForm() { */
$fields = new FieldList( public function TagFieldTestForm()
$tagField = new TagField('Tags', '', new DataList('TagFieldTestBlogTag')) {
); $fields = new FieldList(
$tagField = new TagField('Tags', '', new DataList('TagFieldTestBlogTag'))
);
$actions = new FieldList( $actions = new FieldList(
new FormAction('TagFieldTestFormSubmit') new FormAction('TagFieldTestFormSubmit')
); );
return new Form($this, 'TagFieldTestForm', $fields, $actions); return new Form($this, 'TagFieldTestForm', $fields, $actions);
} }
/** /**
* @param DataObject $dataObject * @param DataObject $dataObject
* @param Form $form * @param Form $form
*/ */
public function TagFieldTestFormSubmit(DataObject $dataObject, Form $form) { public function TagFieldTestFormSubmit(DataObject $dataObject, Form $form)
$form->saveInto($dataObject); {
} $form->saveInto($dataObject);
}
} }