Skip to content
This repository has been archived by the owner on Feb 4, 2022. It is now read-only.

Refactor ViewJson #106

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions code/database/behavior/creatable.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public function getAuthor()
{
$user = null;

if($this->hasProperty('created_by') && !empty($this->created_by)) {
if(!empty($this->created_by)) {
$user = $this->getObject('user.provider')->getUser($this->created_by);
}

Expand Down Expand Up @@ -68,11 +68,11 @@ protected function _beforeInsert(DatabaseContext $context)
$mixer = $this->getMixer();
$table = $mixer instanceof DatabaseRowInterface ? $mixer->getTable() : $mixer;

if($this->hasProperty('created_by') && empty($this->created_by)) {
if(empty($this->created_by)) {
$this->created_by = (int) $this->getObject('user')->getId();
}

if($this->hasProperty('created_on') && (empty($this->created_on) || $this->created_on == $table->getDefault('created_on'))) {
if(empty($this->created_on) || $this->created_on == $table->getDefault('created_on')) {
$this->created_on = gmdate('Y-m-d H:i:s');
}
}
Expand Down
4 changes: 2 additions & 2 deletions code/database/behavior/identifiable.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ protected function _afterSelect(DatabaseContext $context)
{
if($this->getMixer() instanceof DatabaseRowInterface && $this->_auto_generate && !$this->isNew())
{
if($this->hasProperty('uuid') && empty($this->uuid))
if(empty($this->uuid))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't this apply if the table has no uuid col?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No the isSupported() method explicitly check if the table has a uuid column. No need to double check it.

{
$hex = $this->getTable()->getColumn('uuid')->type == 'char' ? false : true;
$this->uuid = $this->_uuid($hex);
Expand All @@ -113,7 +113,7 @@ protected function _beforeInsert(DatabaseContextInterface $context)
{
if($this->getMixer() instanceof DatabaseRowInterface)
{
if($this->hasProperty('uuid') && empty($this->uuid))
if(empty($this->uuid))
{
$hex = $this->getTable()->getColumn('uuid')->type == 'char' ? false : true;
$this->uuid = $this->_uuid($hex);
Expand Down
2 changes: 1 addition & 1 deletion code/database/behavior/lockable.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function getLocker()
{
$user = null;

if($this->hasProperty('locked_by') && !empty($this->locked_by)) {
if(!empty($this->locked_by)) {
$user = $this->getObject('user.provider')->load($this->locked_by);
}

Expand Down
11 changes: 3 additions & 8 deletions code/database/behavior/modifiable.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public function getEditor()
{
$user = null;

if($this->hasProperty('modified_by') && !empty($this->modified_by)) {
if(!empty($this->modified_by)) {
$user = $this->getObject('user.provider')->getUser($this->modified_by);
}

Expand Down Expand Up @@ -82,13 +82,8 @@ public function isSupported()
*/
protected function _beforeInsert(DatabaseContext $context)
{
if($this->hasProperty('modified_by')) {
$this->modified_by = (int) $this->getObject('user')->getId();
}

if($this->hasProperty('modified_on')) {
$this->modified_on = gmdate('Y-m-d H:i:s');
}
$this->modified_by = (int) $this->getObject('user')->getId();
$this->modified_on = gmdate('Y-m-d H:i:s');
}

/**
Expand Down
13 changes: 5 additions & 8 deletions code/database/behavior/orderable.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,10 @@ protected function getMaxOrdering()
*/
protected function _beforeInsert(DatabaseContextInterface $context)
{
if($this->hasProperty('ordering'))
{
if($this->ordering <= 0) {
$this->ordering = $this->getMaxOrdering() + 1;
} else {
$this->reorder($this->ordering);
}
if($this->ordering <= 0) {
$this->ordering = $this->getMaxOrdering() + 1;
} else {
$this->reorder($this->ordering);
}
}

Expand All @@ -192,7 +189,7 @@ protected function _beforeInsert(DatabaseContextInterface $context)
*/
protected function _beforeUpdate(DatabaseContextInterface $context)
{
if(isset($this->order) && $this->hasProperty('ordering')) {
if(isset($this->order)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the property be ordering?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The refactor doesn't touch that, it only removes the additional check for 'ordering'.

$this->order($this->order);
}
}
Expand Down
30 changes: 13 additions & 17 deletions code/database/behavior/parameterizable.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,32 +72,28 @@ protected function _initialize(ObjectConfig $config)
public function getParameters()
{
$result = false;
$handle = $this->getMixer()->getHandle();

if($this->hasProperty($this->_column))
if(!isset($this->_parameters[$handle]))
{
$handle = $this->getMixer()->getHandle();
$type = (array) $this->getTable()->getColumn($this->_column)->filter;
$data = $this->getProperty($this->_column);
$config = $this->getObject('object.config.factory')->createFormat($type[0]);

if(!isset($this->_parameters[$handle]))
if(!empty($data))
{
$type = (array) $this->getTable()->getColumn($this->_column)->filter;
$data = $this->getProperty($this->_column);
$config = $this->getObject('object.config.factory')->createFormat($type[0]);

if(!empty($data))
{
if (is_string($data)) {
$config->fromString(trim($data));
} else {
$config->append($data);
}
if (is_string($data)) {
$config->fromString(trim($data));
} else {
$config->append($data);
}

$this->_parameters[$handle] = $config;
}

$result = $this->_parameters[$handle];
$this->_parameters[$handle] = $config;
}

$result = $this->_parameters[$handle];

return $result;
}

Expand Down
4 changes: 0 additions & 4 deletions code/database/row/abstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,6 @@ public function clear()
$this->__modified_properties = array();
$this->setStatus(NULL);

if ($this->isConnected()) {
$this->_data = $this->getTable()->getDefaults();
}

return $this;
}

Expand Down
3 changes: 3 additions & 0 deletions code/database/rowset/abstract.php
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,9 @@ public function contains($row)
*/
public function create(array $properties = array(), $status = null)
{
//Merge the default properties
$properties = array_merge($this->getTable()->getDefaults(), $properties);

if($this->_prototypable)
{
if(!$this->_prototype instanceof DatabaseRowInterface) {
Expand Down
112 changes: 112 additions & 0 deletions code/model/behavior/sparsable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php
/**
* Kodekit - http://timble.net/kodekit
*
* @copyright Copyright (C) 2007 - 2016 Johan Janssens and Timble CVBA. (http://www.timble.net)
* @license MPL v2.0 <https://www.mozilla.org/en-US/MPL/2.0>
* @link https://github.com/timble/kodekit for the canonical source repository
*/

namespace Kodekit\Library;

/**
* Sparsable Model Behavior
*
* By making a model sparsable, you enables the ability for clients to choose the returned properties of a model
* entity with URL query parameters. This is useful for optimizing requests, making API calls more efficient
* and fast.
*
* A client can request to get only specific fields in the response by including a fields[TYPE] parameter. The
* value of the fields parameter MUST be a comma-separated (U+002C COMMA, “,”) list that refers to the name(s)
* of the fields to be returned.
*
* The behavior will ALAWYS include the identity key property of the specific type in the returned properties.
*
* Based on the Sparse Fieldsets specification in the JSON API
* @link http://jsonapi.org/format/#fetching-sparse-fieldsets
*
* @author Johan Janssens <https://github.com/johanjanssens>
* @package Kodekit\Library\Model\Behavior
*/
class ModelBehaviorSparsable extends ModelBehaviorAbstract
{
/**
* Insert the model states
*
* @param ObjectMixable $mixer
*/
public function onMixin(ObjectMixable $mixer)
{
parent::onMixin($mixer);

$mixer->getState()
->insert('fields', 'cmd', array());
}

/**
* Parse the fields state
*
* @param ModelContextInterface $context A model context object
* @return void
*/
protected function _afterReset(ModelContextInterface $context)
{
if($context->modified->contains('fields'))
{
$fields = $context->state->fields;

foreach ($fields as $type => $value)
{
if(is_string($value)) {
$fields[$type] = array_unique(explode(',', $value));
}
}

$context->state->fields = $fields;
}
}

/**
* Add query colums based on fields
*
* @param ModelContextInterface $context A model context object
* @return void
*/
protected function _beforeFetch(ModelContextInterface $context)
{
$model = $context->getSubject();

$result = array();
$columns = $this->getTable()->getColumns(true);

if ($model instanceof ModelDatabase)
{
$fields = $context->state->fields;
$type = $model->getIdentifier()->name;

if(isset($fields[$type]))
{
$result = array();
$columns = array_keys($this->getTable()->getColumns());

foreach($fields[$type] as $field)
{
if(in_array($field, $columns))
{
$column = $this->getTable()->mapColumns($field);
$result[] = 'tbl.'.$column;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it worth checking the colum exists as a table colum, OR exists as an alias column in the query that's already been constructed. That way, joined columns can also work, currently this would cause an error as tbl.foo may not exist, but foo, may, as a joined/aliased colum.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checking the query itself is out of scope. Not trying to solve problems that are not there. If a situation occurs where checking the query should be needed you can extend the behavior in your own component.

}
}

if(!empty($result))
{
$context->query->columns = array();

//Always include the identity column
$result[] = 'tbl.'.$this->getTable()->getIdentityColumn();
$context->query->columns($result);
}
}
}
}
}
2 changes: 1 addition & 1 deletion code/model/database.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ protected function _initialize(ObjectConfig $config)
{
$config->append(array(
'table' => $this->getIdentifier()->name,
'behaviors' => array('paginatable', 'sortable'),
'behaviors' => array('paginatable', 'sortable', 'sparsable'),
));

parent::_initialize($config);
Expand Down
73 changes: 73 additions & 0 deletions code/view/behavior/routable.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,44 @@
*/
class ViewBehaviorRoutable extends ViewBehaviorAbstract
{
/**
* A list of entity properties to route
*
* URLs will be converted to fully qualified ones in these fields.
*
* @var string
*/
protected $_properties;

/**
* Constructor
*
* @param ObjectConfig $config Configuration options
*/
public function __construct(ObjectConfig $config)
{
parent::__construct($config);

$this->_properties = ObjectConfig::unbox($config->properties);
}

/**
* Initializes the config for the object
*
* Called from {@link __construct()} as a first step of object instantiation.
*
* @param ObjectConfig $config Configuration options
* @return void
*/
protected function _initialize(ObjectConfig $config)
{
$config->append(array(
'properties' => array('description'), // Links are converted to absolute ones in these properties
));

parent::_initialize($config);
}

/**
* Register a route() function in the template
*
Expand All @@ -25,12 +63,47 @@ class ViewBehaviorRoutable extends ViewBehaviorAbstract
*/
protected function _beforeRender(ViewContextInterface $context)
{
//Register 'route' method in template
if($context->subject instanceof ViewTemplatable)
{
$context->subject
->getTemplate()
->registerFunction('route', array($this, 'getRoute'));
}

//Fully quality URL's in entity properties
if($this->getFormat() != 'html')
{
foreach($context->entity as $entity)
{
foreach($this->_properties as $property)
{
$value = $entity->getProperty($property);

if(is_string($value) && !empty($value))
{
$matches = array();
preg_match_all("/(href|src)=\"(?!http|ftp|https|mailto|data)([^\"]*)\"/", $value, $matches, PREG_SET_ORDER);

foreach ($matches as $match)
{
$route = $this->getObject('lib:dispatcher.router.route', array(
'url' => $match[2],
'escape' => $this->getUrl()->isEscaped()
));

//Add the host and the schema
$route->scheme = $this->getUrl()->scheme;
$route->host = $this->getUrl()->host;

$value = str_replace($match[0], $match[1].'="'.$route.'"', $value);
}

$entity->setProperty($property, $value, false);
}
}
}
}
}

/**
Expand Down
Loading