Skip to content

Commit

Permalink
Turn posts_tags into a full post value table, and avoid duplicating info
Browse files Browse the repository at this point in the history
- Add extra field to posts_tags
- Remove tags from post_varchar
- Add Post/Tags validator
- Add Post/Tags repo
  • Loading branch information
rjmackay committed May 22, 2017
1 parent e09837e commit 72ae137
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 69 deletions.
7 changes: 7 additions & 0 deletions application/classes/Ushahidi/Core.php
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ public static function init()
$di->set('repository.post.markdown', $di->lazyNew('Ushahidi_Repository_Post_Markdown'));
$di->set('repository.post.title', $di->lazyNew('Ushahidi_Repository_Post_Title'));
$di->set('repository.post.media', $di->lazyNew('Ushahidi_Repository_Post_Media'));
$di->set('repository.post.tags', $di->lazyNew('Ushahidi_Repository_Post_Tags'));

// The post value repo factory
$di->set('repository.post_value_factory', $di->lazyNew('Ushahidi_Repository_Post_ValueFactory'));
Expand All @@ -483,6 +484,7 @@ public static function init()
'markdown' => $di->lazyGet('repository.post.markdown'),
'title' => $di->lazyGet('repository.post.title'),
'media' => $di->lazyGet('repository.post.media'),
'tags' => $di->lazyGet('repository.post.tags'),
],
];

Expand Down Expand Up @@ -621,6 +623,10 @@ public static function init()
$di->params['Ushahidi_Validator_Post_Media'] = [
'media_repo' => $di->lazyGet('repository.media')
];
$di->set('validator.post.tags', $di->lazyNew('Ushahidi_Validator_Post_Tags'));
$di->params['Ushahidi_Validator_Post_Tags'] = [
'media_repo' => $di->lazyGet('repository.tags')
];


$di->set('validator.post.value_factory', $di->lazyNew('Ushahidi_Validator_Post_ValueFactory'));
Expand All @@ -639,6 +645,7 @@ public static function init()
'title' => $di->lazyGet('validator.post.title'),
'media' => $di->lazyGet('validator.post.media'),
'video' => $di->lazyGet('validator.post.video'),
'tags' => $di->lazyGet('validator.post.tags'),
],
];

Expand Down
60 changes: 60 additions & 0 deletions application/classes/Ushahidi/Repository/Post/Tags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi Post Relation Repository
*
* @author Ushahidi Team <team@ushahidi.com>
* @package Ushahidi\Application
* @copyright 2014 Ushahidi
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3)
*/

class Ushahidi_Repository_Post_Tags extends Ushahidi_Repository_Post_Value
{
// Ushahidi_Repository
protected function getTable()
{
return 'posts_tags';
}

// Override selectQuery to fetch attribute 'key' too
protected function selectQuery(Array $where = [])
{
$query = parent::selectQuery($where);

// Select 'tag_id' as value too
$query->select(
['posts_tags.tag_id', 'value']
);

return $query;
}

// PostValueRepository
public function getValueQuery($form_attribute_id, $match)
{
return $this->selectQuery(compact('form_attribute_id'))
->where('tag_id', 'LIKE', "%$match%");
}

// UpdatePostValueRepository
public function createValue($value, $form_attribute_id, $post_id)
{
$tag_id = $value;
$input = compact('tag_id', 'form_attribute_id', 'post_id');
$input['created'] = time();

return $this->executeInsert($input);
}

// UpdatePostValueRepository
public function updateValue($id, $value)
{
$update = ['tag_id' => $value];
if ($id && $update)
{
$this->executeUpdate(compact('id'), $update);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public function formStageBelongsToForm($value)
public function canMakePrivate($value, $input)
{
// If input type is tags, then attribute cannot be private
if ($input === 'tags' && $value !== false) {
if ($type === 'tags' && $value !== false) {
return false;
}

Expand Down
33 changes: 33 additions & 0 deletions application/classes/Ushahidi/Validator/Post/Tags.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php defined('SYSPATH') OR die('No direct access allowed.');

/**
* Ushahidi Post Media Validator
*
* @author Ushahidi Team <team@ushahidi.com>
* @package Ushahidi\Application
* @copyright 2014 Ushahidi
* @license https://www.gnu.org/licenses/agpl-3.0.html GNU Affero General Public License Version 3 (AGPL3)
*/

use Ushahidi\Core\Entity\TagsRepository;

class Ushahidi_Validator_Post_Tags extends Ushahidi_Validator_Post_ValueValidator
{
protected $media_repo;

public function __construct(TagsRepository $tags_repo)
{
$this->repo = $tags_repo;
}

protected function validate($value)
{
if (!Valid::digit($value)) {
return 'digit';
}

if (! $this->repo->exists($value)) {
return 'exists';
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,6 @@ public function up()
*/
public function down()
{
$this->execute("DELETE from form_attributes where input = 'tags'");
$this->execute("DELETE from form_attributes where type = 'varchar' AND input = 'tags'");
}
}
111 changes: 44 additions & 67 deletions migrations/20170417090621_move_post_tag_values_to_post_varchar.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,81 +9,58 @@ class MovePostTagValuesToPostVarchar extends AbstractMigration
*/
public function up()
{
$pdo = $this->getAdapter()->getConnection();
// fetching posts with form_attribute_id
$posts = $this->fetchAll(
"SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id
FROM posts
INNER JOIN form_stages
ON form_stages.form_id = posts.form_id
INNER JOIN form_attributes
ON form_attributes.form_stage_id = form_stages.id"
);
$insert = $pdo->prepare(
"INSERT into
post_varchar
(`post_id`, `form_attribute_id`, `value`, `created`)
VALUES(:post_id, :form_attribute_id, :value, :created)"
);
foreach ($posts as $post) {
$post_tags = $pdo->prepare(
"SELECT tag_id
FROM posts_tags
WHERE post_id = :post_id"
);
$post_tags->execute([':post_id' => $post['id']]);
// inserting post_ids and tag_ids(value) in post_varchar
$tags = $post_tags->fetchAll();
foreach ($tags as $tag) {
$insert->execute(
[
':post_id' => $post['id'],
':form_attribute_id' => $post['form_attribute_id'],
':value' => $tag['tag_id'],
':created' => time()
]
);
}
}
// Don't do this if we haven't already!
// We have a better way.

//$pdo = $this->getAdapter()->getConnection();
// fetching posts with form_attribute_id
// $posts = $this->fetchAll(
// "SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id
// FROM posts
// INNER JOIN form_stages
// ON form_stages.form_id = posts.form_id
// INNER JOIN form_attributes
// ON form_attributes.form_stage_id = form_stages.id
// AND form_attributes.input = 'tags'
// AND form_attributes.type = 'varchar'"
// );
// $insert = $pdo->prepare(
// "INSERT into
// post_varchar
// (`post_id`, `form_attribute_id`, `value`, `created`)
// VALUES(:post_id, :form_attribute_id, :value, :created)"
// );
// foreach ($posts as $post) {
// $post_tags = $pdo->prepare(
// "SELECT tag_id
// FROM posts_tags
// WHERE post_id = :post_id"
// );
// $post_tags->execute([':post_id' => $post['id']]);
// // inserting post_ids and tag_ids(value) in post_varchar
// $tags = $post_tags->fetchAll();
// foreach ($tags as $tag) {
// $insert->execute(
// [
// ':post_id' => $post['id'],
// ':form_attribute_id' => $post['form_attribute_id'],
// ':value' => $tag['tag_id'],
// ':created' => time()
// ]
// );
// }
// }
}

/**
* Migrate Down.
*/
public function down()
{
$pdo = $this->getAdapter()->getConnection();
$posts = $this->fetchAll(
"SELECT posts.id, posts.form_id, form_attributes.id as form_attribute_id
FROM posts
INNER JOIN form_stages
ON form_stages.form_id = posts.form_id
INNER JOIN form_attributes
ON form_attributes.form_stage_id = form_stages.id"
);
$delete = $pdo->prepare(
$this->execute(
"DELETE from post_varchar
WHERE post_id = :post_id AND form_attribute_id = :form_attribute_id AND value = :value"
WHERE form_attribute_id IN
(SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')"
);

foreach ($posts as $post) {
$post_tags = $pdo->prepare(
"SELECT tag_id
FROM posts_tags
WHERE post_id = :post_id"
);
$post_tags->execute([':post_id' => $post['id']]);
// inserting post_ids and tag_ids(value) in post_varchar
$tags = $post_tags->fetchAll();
foreach ($tags as $tag) {
$delete->execute(
[
':post_id' => $post['id'],
':form_attribute_id' => $post['form_attribute_id'],
':value' => $tag['tag_id']
]
);
}
}
}
}
21 changes: 21 additions & 0 deletions migrations/20170522004400_remove_tags_from_post_varchar.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

use Phinx\Migration\AbstractMigration;

class RemoveTagsFromPostVarchar extends AbstractMigration
{
public function up()
{
// Remove all tag values from post_varchar
$this->execute(
"DELETE from post_varchar
WHERE form_attribute_id IN
(SELECT form_attributes.id FROM form_attributes WHERE input = 'tags' AND type = 'varchar')"
);
}

public function down()
{
// No op - not reversible
}
}
86 changes: 86 additions & 0 deletions migrations/20170522004409_join_posts_tags_table_to_attribute.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

use Phinx\Migration\AbstractMigration;

class JoinPostsTagsTableToAttribute extends AbstractMigration
{
public function up()
{
$pdo = $this->getAdapter()->getConnection();

$this->table('posts_tags')
->addColumn('id', 'integer', ['null' => false])
->addColumn('form_attribute_id', 'integer')
->addColumn('created', 'integer', ['default' => 0])
->update();

// Manually fix up keys
$this->execute('ALTER TABLE posts_tags
DROP PRIMARY KEY,
ADD PRIMARY KEY (id),
ADD INDEX (post_id),
MODIFY COLUMN id INT AUTO_INCREMENT,
ADD UNIQUE INDEX unique_post_tag_attribute_ids (post_id, tag_id, form_attribute_id)');

// Make varchar/tags attributes into tags/tags attributes
$this->execute("
UPDATE form_attributes
SET type = 'tags'
WHERE type = 'varchar' AND input = 'tags'
");

$attributes = $this->fetchAll("
SELECT form_attributes.id, form_stages.form_id
FROM form_attributes
JOIN form_stages ON (form_attributes.form_stage_id = form_stages.id)
WHERE
form_attributes.type = 'tags' AND
form_stages.type = 'post'
");

// Set form_attribute_id for posts_tags entries
$insert = $pdo->prepare('
UPDATE posts_tags JOIN posts ON (posts_tags.post_id = posts.id)
SET form_attribute_id = :attr_id WHERE posts.form_id = :form_id
');
foreach ($attributes as $attribute) {
$insert->execute([
':attr_id' => $attribute['id'],
':form_id' => $attribute['form_id']
]);
}

// Add foreign key for form_attribute_id
$this->table('posts_tags')
->addForeignKey('form_attribute_id', 'form_attributes', 'id', [
'delete' => 'CASCADE',
'update' => 'CASCADE',
])
->update();
}

public function down()
{
// Make tags/tags attributes into varchar/tags attributes
$this->execute("
UPDATE form_attributes
SET type = 'varchar'
WHERE type = 'tags' AND input = 'tags'
");

// Restore keys/indexs
$this->execute('ALTER TABLE posts_tags
DROP PRIMARY KEY,
ADD PRIMARY KEY (post_id, tag_id),
MODIFY COLUMN id INT,
DROP INDEX unique_post_tag_attribute_ids');

// Remove columns
$this->table('posts_tags')
->dropForeignKey('form_attribute_id')
->removeColumn('id')
->removeColumn('form_attribute_id')
->removeColumn('created')
->update();
}
}
Loading

0 comments on commit 72ae137

Please sign in to comment.