diff --git a/TODO b/TODO
index f67d6884..c217c8d6 100644
--- a/TODO
+++ b/TODO
@@ -28,16 +28,6 @@ everything related to tags:
- tag editing
- category (from config.ini)
- description
- - aliases
- - take care of recursion
- - listing
- - sort alphabetically
- - sort by time of addition
- - adding
- - removing
- - editing
- - from
- - to (allow multiple)
- implications - when entering child tag, add parent tag
- take care of recursion
- listing
diff --git a/data/config.ini b/data/config.ini
index 2686cdc2..489853c6 100644
--- a/data/config.ini
+++ b/data/config.ini
@@ -60,6 +60,7 @@ changePostFlags = regularUser, powerUser, moderator, administrator
listTags = regularUser, powerUser, moderator, administrator
massTag = powerUser, moderator, administrator
changeTagName = moderator, administrator
+banTags = moderator, administrator
listComments = regularUser, powerUser, moderator, administrator
addComments = regularUser, powerUser, moderator, administrator
diff --git a/public_html/js/Auth.js b/public_html/js/Auth.js
index 8d24d97b..d095f094 100644
--- a/public_html/js/Auth.js
+++ b/public_html/js/Auth.js
@@ -45,6 +45,7 @@ App.Auth = function(_, jQuery, util, api, appState, promise) {
listTags: 'listTags',
massTag: 'massTag',
changeTagName: 'changeTagName',
+ banTags: 'banTags',
viewHistory: 'viewHistory',
};
diff --git a/public_html/js/Presenters/TagPresenter.js b/public_html/js/Presenters/TagPresenter.js
index 88390209..e13ebe78 100644
--- a/public_html/js/Presenters/TagPresenter.js
+++ b/public_html/js/Presenters/TagPresenter.js
@@ -28,6 +28,7 @@ App.Presenters.TagPresenter = function(
topNavigationPresenter.changeTitle('Tags');
privileges.canChangeName = auth.hasPrivilege(auth.privileges.changeTagName);
+ privileges.canBan = auth.hasPrivilege(auth.privileges.banTags);
promise.wait(
util.promiseTemplate('tag'),
@@ -81,6 +82,10 @@ App.Presenters.TagPresenter = function(
formData.name = $form.find('[name=name]').val();
}
+ if (privileges.canBan) {
+ formData.banned = $form.find('[name=ban]').is(':checked') ? 1 : 0;
+ }
+
promise.wait(api.put('/tags/' + tag.name, formData))
.then(function(response) {
tag = response.json;
diff --git a/public_html/templates/tag.tpl b/public_html/templates/tag.tpl
index 48ccc569..f0c7c0b6 100644
--- a/public_html/templates/tag.tpl
+++ b/public_html/templates/tag.tpl
@@ -14,6 +14,18 @@
<% } %>
+ <% if (privileges.canBan) { %>
+
+ <% } %>
+
diff --git a/src/Controllers/TagController.php b/src/Controllers/TagController.php
index 3b5c34a8..a4531477 100644
--- a/src/Controllers/TagController.php
+++ b/src/Controllers/TagController.php
@@ -81,6 +81,9 @@ final class TagController extends AbstractController
if ($formData->name !== null)
$this->privilegeService->assertPrivilege(Privilege::CHANGE_TAG_NAME);
+ if ($formData->banned !== null)
+ $this->privilegeService->assertPrivilege(Privilege::BAN_TAGS);
+
$tag = $this->tagService->updateTag($tag, $formData);
return $this->tagViewProxy->fromEntity($tag);
}
diff --git a/src/Controllers/ViewProxies/TagViewProxy.php b/src/Controllers/ViewProxies/TagViewProxy.php
index 6a4ad7d4..c0d38619 100644
--- a/src/Controllers/ViewProxies/TagViewProxy.php
+++ b/src/Controllers/ViewProxies/TagViewProxy.php
@@ -10,6 +10,7 @@ class TagViewProxy extends AbstractViewProxy
{
$result->name = $tag->getName();
$result->usages = $tag->getUsages();
+ $result->banned = $tag->isBanned();
}
return $result;
}
diff --git a/src/Dao/EntityConverters/TagEntityConverter.php b/src/Dao/EntityConverters/TagEntityConverter.php
index c25a4341..d80cba99 100644
--- a/src/Dao/EntityConverters/TagEntityConverter.php
+++ b/src/Dao/EntityConverters/TagEntityConverter.php
@@ -12,6 +12,7 @@ class TagEntityConverter extends AbstractEntityConverter implements IEntityConve
'id' => $entity->getId(),
'name' => $entity->getName(),
'creationTime' => $this->entityTimeToDbTime($entity->getCreationTime()),
+ 'banned' => $entity->isBanned(),
];
}
@@ -21,6 +22,7 @@ class TagEntityConverter extends AbstractEntityConverter implements IEntityConve
$entity->setName($array['name']);
$entity->setCreationTime($this->dbTimeToEntityTime($array['creationTime']));
$entity->setMeta(Tag::META_USAGES, intval($array['usages']));
+ $entity->setBanned($array['banned']);
return $entity;
}
}
diff --git a/src/Entities/Tag.php b/src/Entities/Tag.php
index 178b8b25..ecd8f596 100644
--- a/src/Entities/Tag.php
+++ b/src/Entities/Tag.php
@@ -5,6 +5,7 @@ final class Tag extends Entity
{
private $name;
private $creationTime;
+ private $banned = false;
const META_USAGES = 'usages';
@@ -23,6 +24,16 @@ final class Tag extends Entity
return $this->creationTime;
}
+ public function isBanned()
+ {
+ return $this->banned;
+ }
+
+ public function setBanned($banned)
+ {
+ $this->banned = boolval($banned);
+ }
+
public function setCreationTime($creationTime)
{
$this->creationTime = $creationTime;
diff --git a/src/FormData/TagEditFormData.php b/src/FormData/TagEditFormData.php
index fb5cbd91..51eb7ba2 100644
--- a/src/FormData/TagEditFormData.php
+++ b/src/FormData/TagEditFormData.php
@@ -6,12 +6,15 @@ use Szurubooru\Validator;
class TagEditFormData implements IValidatable
{
public $name;
+ public $banned;
public function __construct($inputReader = null)
{
if ($inputReader !== null)
{
$this->name = $inputReader->name;
+ if ($inputReader->banned !== null)
+ $this->banned = boolval($inputReader->banned);
}
}
diff --git a/src/Privilege.php b/src/Privilege.php
index 33238a2b..3369de56 100644
--- a/src/Privilege.php
+++ b/src/Privilege.php
@@ -38,6 +38,7 @@ class Privilege
const LIST_TAGS = 'listTags';
const MASS_TAG = 'massTag';
const CHANGE_TAG_NAME = 'changeTagName';
+ const BAN_TAGS = 'banTags';
const LIST_COMMENTS = 'listComments';
const ADD_COMMENTS = 'addComments';
diff --git a/src/Services/PostService.php b/src/Services/PostService.php
index e88f6fed..13ad92f5 100644
--- a/src/Services/PostService.php
+++ b/src/Services/PostService.php
@@ -303,6 +303,11 @@ class PostService
$tags[] = $tag;
}
$tags = $this->tagService->createTags($tags);
+ foreach ($tags as $tag)
+ {
+ if ($tag->isBanned())
+ throw new \DomainException('Cannot use banned tag "' . $tag->getName() . '"');
+ }
$post->setTags($tags);
}
diff --git a/src/Services/TagService.php b/src/Services/TagService.php
index 12f6c23e..4c630a80 100644
--- a/src/Services/TagService.php
+++ b/src/Services/TagService.php
@@ -75,7 +75,8 @@ class TagService
{
$tags[$tag->getId()] = [
'name' => $tag->getName(),
- 'usages' => $tag->getUsages()];
+ 'usages' => $tag->getUsages(),
+ 'banned' => $tag->isBanned()];
}
$json = json_encode($tags);
$this->fileDao->save('tags.json', $json);
@@ -141,6 +142,9 @@ class TagService
if ($formData->name !== null)
$this->updateTagName($tag, $formData->name);
+ if ($formData->banned !== $tag->isBanned())
+ $tag->setBanned(boolval($formData->banned));
+
return $this->tagDao->save($tag);
};
$ret = $this->transactionManager->commit($transactionFunc);
diff --git a/src/Upgrades/Upgrade23.php b/src/Upgrades/Upgrade23.php
new file mode 100644
index 00000000..a0b0ef1a
--- /dev/null
+++ b/src/Upgrades/Upgrade23.php
@@ -0,0 +1,22 @@
+tagService = $tagService;
+ }
+
+ public function run(DatabaseConnection $databaseConnection)
+ {
+ $pdo = $databaseConnection->getPDO();
+ $pdo->exec('ALTER TABLE tags ADD COLUMN banned BOOLEAN NOT NULL DEFAULT 0');
+
+ $this->tagService->exportJson();
+ }
+}
diff --git a/src/di.php b/src/di.php
index fd7767c1..2d040a95 100644
--- a/src/di.php
+++ b/src/di.php
@@ -38,6 +38,7 @@ return [
$container->get(\Szurubooru\Upgrades\Upgrade20::class),
$container->get(\Szurubooru\Upgrades\Upgrade21::class),
$container->get(\Szurubooru\Upgrades\Upgrade22::class),
+ $container->get(\Szurubooru\Upgrades\Upgrade23::class),
];
}),
diff --git a/tests/Dao/TagDaoTest.php b/tests/Dao/TagDaoTest.php
index 019d7265..a054da4b 100644
--- a/tests/Dao/TagDaoTest.php
+++ b/tests/Dao/TagDaoTest.php
@@ -11,6 +11,20 @@ final class TagDaoTest extends AbstractDatabaseTestCase
parent::setUp();
}
+ public function testSaving()
+ {
+ $tag = new Tag();
+ $tag->setName('test1');
+ $tag->setCreationTime(date('c', mktime(0, 0, 0, 10, 1, 2014)));
+ $this->assertFalse($tag->isBanned());
+ $tag->setBanned(true);
+
+ $tagDao = $this->getTagDao();
+ $tagDao->save($tag);
+ $actualTag = $tagDao->findById($tag->getId());
+ $this->assertEntitiesEqual($tag, $actualTag);
+ }
+
public function testFindByPostIds()
{
$pdo = $this->databaseConnection->getPDO();
diff --git a/tests/Services/TagServiceTest.php b/tests/Services/TagServiceTest.php
index ca55796d..343bbc1d 100644
--- a/tests/Services/TagServiceTest.php
+++ b/tests/Services/TagServiceTest.php
@@ -78,7 +78,7 @@ final class TagServiceTest extends AbstractDatabaseTestCase
$tagService = $this->getTagService();
$tagService->createTags([$tag1]);
$tagService->exportJson();
- $this->assertEquals('{"1":{"name":"test","usages":0}}', $fileDao->load('tags.json'));
+ $this->assertEquals('{"1":{"name":"test","usages":0,"banned":false}}', $fileDao->load('tags.json'));
}
public function testExportMultiple()
@@ -89,11 +89,12 @@ final class TagServiceTest extends AbstractDatabaseTestCase
$tag2 = new Tag();
$tag2->setName('test2');
$tag2->setCreationTime(date('c'));
+ $tag2->setBanned(true);
$fileDao = $this->getPublicFileDao();
$tagService = $this->getTagService();
$tagService->createTags([$tag1, $tag2]);
$tagService->exportJson();
- $this->assertEquals('{"1":{"name":"test1","usages":0},"2":{"name":"test2","usages":0}}', $fileDao->load('tags.json'));
+ $this->assertEquals('{"1":{"name":"test1","usages":0,"banned":false},"2":{"name":"test2","usages":0,"banned":true}}', $fileDao->load('tags.json'));
}
private function getPublicFileDao()