Added sorting by tag usage dates to tag list
This commit is contained in:
parent
c1f8a5e632
commit
9e29441c68
7 changed files with 124 additions and 36 deletions
|
@ -4,6 +4,8 @@ use \Chibi\Sql as Sql;
|
||||||
final class TagEntity extends AbstractEntity implements IValidatable, ISerializable
|
final class TagEntity extends AbstractEntity implements IValidatable, ISerializable
|
||||||
{
|
{
|
||||||
private $name;
|
private $name;
|
||||||
|
private $creationDate;
|
||||||
|
private $updateDate;
|
||||||
|
|
||||||
public function fillNew()
|
public function fillNew()
|
||||||
{
|
{
|
||||||
|
@ -13,6 +15,8 @@ final class TagEntity extends AbstractEntity implements IValidatable, ISerializa
|
||||||
{
|
{
|
||||||
$this->id = (int) $row['id'];
|
$this->id = (int) $row['id'];
|
||||||
$this->name = $row['name'];
|
$this->name = $row['name'];
|
||||||
|
$this->creationDate = TextHelper::toIntegerOrNull($row['creation_date']);
|
||||||
|
$this->updateDate = TextHelper::toIntegerOrNull($row['update_date']);
|
||||||
|
|
||||||
if (isset($row['post_count']))
|
if (isset($row['post_count']))
|
||||||
$this->setCache('post_count', (int) $row['post_count']);
|
$this->setCache('post_count', (int) $row['post_count']);
|
||||||
|
@ -57,6 +61,16 @@ final class TagEntity extends AbstractEntity implements IValidatable, ISerializa
|
||||||
return $this->name;
|
return $this->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getCreationDate()
|
||||||
|
{
|
||||||
|
return $this->creationDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpdateDate()
|
||||||
|
{
|
||||||
|
return $this->updateDate;
|
||||||
|
}
|
||||||
|
|
||||||
public function getPostCount()
|
public function getPostCount()
|
||||||
{
|
{
|
||||||
if ($this->hasCache('post_count'))
|
if ($this->hasCache('post_count'))
|
||||||
|
|
|
@ -43,47 +43,69 @@ final class PostModel extends AbstractCrudModel
|
||||||
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($post->getId())));
|
$stmt->setCriterion(Sql\Functors::equals('id', new Sql\Binding($post->getId())));
|
||||||
Core::getDatabase()->execute($stmt);
|
Core::getDatabase()->execute($stmt);
|
||||||
|
|
||||||
//tags
|
self::saveTags($post);
|
||||||
$tags = $post->getTags();
|
self::saveRelations($post);
|
||||||
|
|
||||||
$stmt = Sql\Statements::delete();
|
|
||||||
$stmt->setTable('post_tag');
|
|
||||||
$stmt->setCriterion(Sql\Functors::equals('post_id', new Sql\Binding($post->getId())));
|
|
||||||
Core::getDatabase()->execute($stmt);
|
|
||||||
|
|
||||||
foreach ($tags as $postTag)
|
|
||||||
{
|
|
||||||
$stmt = Sql\Statements::insert();
|
|
||||||
$stmt->setTable('post_tag');
|
|
||||||
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
|
|
||||||
$stmt->setColumn('tag_id', new Sql\Binding($postTag->getId()));
|
|
||||||
Core::getDatabase()->execute($stmt);
|
|
||||||
}
|
|
||||||
|
|
||||||
//relations
|
|
||||||
$relations = $post->getRelations();
|
|
||||||
|
|
||||||
$stmt = Sql\Statements::delete();
|
|
||||||
$stmt->setTable('crossref');
|
|
||||||
$binding = new Sql\Binding($post->getId());
|
|
||||||
$stmt->setCriterion(Sql\Functors::disjunction()
|
|
||||||
->add(Sql\Functors::equals('post_id', $binding))
|
|
||||||
->add(Sql\Functors::equals('post2_id', $binding)));
|
|
||||||
Core::getDatabase()->execute($stmt);
|
|
||||||
|
|
||||||
foreach ($relations as $relatedPost)
|
|
||||||
{
|
|
||||||
$stmt = Sql\Statements::insert();
|
|
||||||
$stmt->setTable('crossref');
|
|
||||||
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
|
|
||||||
$stmt->setColumn('post2_id', new Sql\Binding($relatedPost->getId()));
|
|
||||||
Core::getDatabase()->execute($stmt);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return $post;
|
return $post;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function saveTags($post)
|
||||||
|
{
|
||||||
|
$newTagIds = array_map(function($tag) { return $tag->getId(); }, $post->getTags());
|
||||||
|
|
||||||
|
$stmt = Sql\Statements::select();
|
||||||
|
$stmt->setTable('post_tag');
|
||||||
|
$stmt->setColumn('tag_id');
|
||||||
|
$stmt->setCriterion(Sql\Functors::equals('post_id', new Sql\Binding($post->getId())));
|
||||||
|
$rows = Core::getDatabase()->fetchAll($stmt);
|
||||||
|
$oldTagIds = array_map(function($row) { return $row['tag_id']; }, $rows);
|
||||||
|
|
||||||
|
$tagIdsToInsert = array_diff($newTagIds, $oldTagIds);
|
||||||
|
$tagIdsToDelete = array_diff($oldTagIds, $newTagIds);
|
||||||
|
|
||||||
|
if (count($tagIdsToDelete))
|
||||||
|
{
|
||||||
|
$stmt = Sql\Statements::delete();
|
||||||
|
$stmt->setTable('post_tag');
|
||||||
|
$stmt->setCriterion(Sql\Functors::conjunction()
|
||||||
|
->add(Sql\Functors::in('tag_id', Sql\Binding::fromArray($tagIdsToDelete)))
|
||||||
|
->add(Sql\Functors::equals('post_id', new Sql\Binding($post->getId()))));
|
||||||
|
Core::getDatabase()->execute($stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($tagIdsToInsert as $tagIdToInsert)
|
||||||
|
{
|
||||||
|
$stmt = Sql\Statements::insert();
|
||||||
|
$stmt->setTable('post_tag');
|
||||||
|
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
|
||||||
|
$stmt->setColumn('tag_id', new Sql\Binding($tagIdToInsert));
|
||||||
|
Core::getDatabase()->execute($stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function saveRelations($post)
|
||||||
|
{
|
||||||
|
$relations = $post->getRelations();
|
||||||
|
|
||||||
|
$stmt = Sql\Statements::delete();
|
||||||
|
$stmt->setTable('crossref');
|
||||||
|
$binding = new Sql\Binding($post->getId());
|
||||||
|
$stmt->setCriterion(Sql\Functors::disjunction()
|
||||||
|
->add(Sql\Functors::equals('post_id', $binding))
|
||||||
|
->add(Sql\Functors::equals('post2_id', $binding)));
|
||||||
|
Core::getDatabase()->execute($stmt);
|
||||||
|
|
||||||
|
foreach ($relations as $relatedPost)
|
||||||
|
{
|
||||||
|
$stmt = Sql\Statements::insert();
|
||||||
|
$stmt->setTable('crossref');
|
||||||
|
$stmt->setColumn('post_id', new Sql\Binding($post->getId()));
|
||||||
|
$stmt->setColumn('post2_id', new Sql\Binding($relatedPost->getId()));
|
||||||
|
Core::getDatabase()->execute($stmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected static function removeSingle($post)
|
protected static function removeSingle($post)
|
||||||
{
|
{
|
||||||
Core::getDatabase()->transaction(function() use ($post)
|
Core::getDatabase()->transaction(function() use ($post)
|
||||||
|
|
|
@ -38,6 +38,10 @@ class TagSearchParser extends AbstractSearchParser
|
||||||
{
|
{
|
||||||
if ($orderByString == 'popularity')
|
if ($orderByString == 'popularity')
|
||||||
$this->statement->setOrderBy('post_count', $orderDir);
|
$this->statement->setOrderBy('post_count', $orderDir);
|
||||||
|
elseif ($orderByString == 'creation_date')
|
||||||
|
$this->statement->setOrderBy('tag.creation_date', $orderDir);
|
||||||
|
elseif ($orderByString == 'update_date')
|
||||||
|
$this->statement->setOrderBy('tag.update_date', $orderDir);
|
||||||
elseif ($orderByString == 'alpha')
|
elseif ($orderByString == 'alpha')
|
||||||
$this->statement->setOrderBy(Sql\Functors::{'case'}('tag.name'), $orderDir);
|
$this->statement->setOrderBy(Sql\Functors::{'case'}('tag.name'), $orderDir);
|
||||||
else
|
else
|
||||||
|
|
15
src/Upgrades/mysql/Upgrade17.sql
Normal file
15
src/Upgrades/mysql/Upgrade17.sql
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
ALTER TABLE tag ADD COLUMN creation_date INTEGER DEFAULT NULL;
|
||||||
|
ALTER TABLE tag ADD COLUMN update_date INTEGER DEFAULT NULL;
|
||||||
|
|
||||||
|
DROP TRIGGER post_tag_insert;
|
||||||
|
CREATE TRIGGER post_tag_insert AFTER INSERT ON post_tag FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE post SET tag_count = tag_count + 1 WHERE post.id = NEW.post_id;
|
||||||
|
UPDATE tag SET update_date = UNIX_TIMESTAMP() WHERE tag.id = NEW.tag_id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tag_insert BEFORE INSERT ON tag FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
SET NEW.creation_date = UNIX_TIMESTAMP();
|
||||||
|
SET NEW.update_date = UNIX_TIMESTAMP();
|
||||||
|
END;
|
15
src/Upgrades/sqlite/Upgrade17.sql
Normal file
15
src/Upgrades/sqlite/Upgrade17.sql
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
ALTER TABLE tag ADD COLUMN creation_date INTEGER DEFAULT NULL;
|
||||||
|
ALTER TABLE tag ADD COLUMN update_date INTEGER DEFAULT NULL;
|
||||||
|
|
||||||
|
DROP TRIGGER post_tag_insert;
|
||||||
|
CREATE TRIGGER post_tag_insert AFTER INSERT ON post_tag FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE post SET tag_count = tag_count + 1 WHERE post.id = NEW.post_id;
|
||||||
|
UPDATE tag SET update_date = STRFTIME('%s', 'NOW') WHERE tag.id = NEW.tag_id;
|
||||||
|
END;
|
||||||
|
|
||||||
|
CREATE TRIGGER tag_insert AFTER INSERT ON tag FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
UPDATE tag SET creation_date = STRFTIME('%s', 'NOW') WHERE tag.id = NEW.id;
|
||||||
|
UPDATE tag SET update_date = STRFTIME('%s', 'NOW') WHERE tag.id = NEW.id;
|
||||||
|
END;
|
|
@ -7,6 +7,8 @@
|
||||||
'order:alpha,desc' => 'Sort Z→A',
|
'order:alpha,desc' => 'Sort Z→A',
|
||||||
'order:popularity,desc' => 'Often used first',
|
'order:popularity,desc' => 'Often used first',
|
||||||
'order:popularity,asc' => 'Rarely used first',
|
'order:popularity,asc' => 'Rarely used first',
|
||||||
|
'order:update_date,desc' => 'Recently used',
|
||||||
|
'order:creation_date,desc' => 'Recently created',
|
||||||
];
|
];
|
||||||
?>
|
?>
|
||||||
|
|
||||||
|
|
16
tests/Tests/ModelTests/TagModelTest.php
Normal file
16
tests/Tests/ModelTests/TagModelTest.php
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<?php
|
||||||
|
class TagModelTest extends AbstractTest
|
||||||
|
{
|
||||||
|
public function testSavingAndRetrieving()
|
||||||
|
{
|
||||||
|
$tag = TagModel::spawn();
|
||||||
|
$tag->setName('test');
|
||||||
|
|
||||||
|
TagModel::save($tag);
|
||||||
|
$otherTag = TagModel::getById($tag->getId());
|
||||||
|
|
||||||
|
$this->assert->areEqual($tag->getName(), $otherTag->getName());
|
||||||
|
$this->assert->areEqual(time(), $otherTag->getCreationDate());
|
||||||
|
$this->assert->areEqual(time(), $otherTag->getUpdateDate());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue