Added relationship set event.

Adjusted relationship set statements for betteer accuracy
This commit is contained in:
matthew 2019-07-05 10:15:38 -05:00 committed by Shish
parent 639c896a16
commit 80e614b53e
2 changed files with 256 additions and 17 deletions

View File

@ -1,13 +1,29 @@
<?php <?php
/** /**
* Name: Post Relationships * Name: Post Relationships
* Author: Angus Johnston <admin@codeanimu.net> * Author: Angus Johnston <admin@codeanimu.net, Matthew Barbour <matthew@darkholme.net>
* License: GPLv2 * License: GPLv2
* Description: Allow posts to have relationships (parent/child). * Description: Allow posts to have relationships (parent/child).
*/ */
class ImageRelationshipSetEvent extends Event
{
public $child_id;
public $parent_id;
public function __construct(int $child_id, int $parent_id)
{
$this->child_id = $child_id;
$this->parent_id = $parent_id;
}
}
class Relationships extends Extension class Relationships extends Extension
{ {
public const NAME = "Relationships";
protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL]; protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL];
public function onInitExt(InitExtEvent $event) public function onInitExt(InitExtEvent $event)
@ -35,7 +51,7 @@ class Relationships extends Extension
{ {
if (isset($_POST['tag_edit__tags']) ? !preg_match('/parent[=|:]/', $_POST["tag_edit__tags"]) : true) { //Ignore tag_edit__parent if tags contain parent metatag if (isset($_POST['tag_edit__tags']) ? !preg_match('/parent[=|:]/', $_POST["tag_edit__tags"]) : true) { //Ignore tag_edit__parent if tags contain parent metatag
if (isset($_POST["tag_edit__parent"]) ? ctype_digit($_POST["tag_edit__parent"]) : false) { if (isset($_POST["tag_edit__parent"]) ? ctype_digit($_POST["tag_edit__parent"]) : false) {
$this->set_parent($event->image->id, (int) $_POST["tag_edit__parent"]); send_event(new ImageRelationshipSetEvent($event->image->id,(int) $_POST["tag_edit__parent"]));
} else { } else {
$this->remove_parent($event->image->id); $this->remove_parent($event->image->id);
} }
@ -75,12 +91,12 @@ class Relationships extends Extension
if ($parentID == "none" || $parentID == "0") { if ($parentID == "none" || $parentID == "0") {
$this->remove_parent($event->id); $this->remove_parent($event->id);
} else { } else {
$this->set_parent($event->id, $parentID); send_event(new ImageRelationshipSetEvent($event->id, $parentID));
} }
} elseif (preg_match("/^child[=|:]([0-9]+)$/", $event->term, $matches) && $event->parse) { } elseif (preg_match("/^child[=|:]([0-9]+)$/", $event->term, $matches) && $event->parse) {
$childID = $matches[1]; $childID = $matches[1];
$this->set_child($event->id, $childID); send_event(new ImageRelationshipSetEvent($childID, $event->id));
} }
if (!empty($matches)) { if (!empty($matches)) {
@ -102,29 +118,45 @@ class Relationships extends Extension
} }
if ($event->image->parent_id !== null) { if ($event->image->parent_id !== null) {
$database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN (COUNT(*) - 1) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub) $this->set_has_children($event->image->parent_id);
WHERE id = :pid", ["pid"=>$event->image->parent_id]);
} }
} }
private function set_parent(int $imageID, int $parentID) public function onImageRelationshipSet(ImageRelationshipSetEvent $event)
{ {
global $database; global $database;
if ($database->get_row("SELECT 1 FROM images WHERE id = :pid", ["pid"=>$parentID])) { $old_parent = $database->get_one("SELECT parent_id FROM images WHERE id = :cid", ["cid"=>$event->child_id]);
$database->execute("UPDATE images SET parent_id = :pid WHERE id = :iid", ["pid"=>$parentID, "iid"=>$imageID]);
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", ["pid"=>$parentID]); if($old_parent!=$event->parent_id) {
if ($database->get_row("SELECT 1 FROM images WHERE id = :pid", ["pid" => $event->parent_id])) {
$result = $database->execute("UPDATE images SET parent_id = :pid WHERE id = :cid", ["pid" => $event->parent_id, "cid" => $event->child_id]);
if ($result->rowCount() > 0) {
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", ["pid" => $event->parent_id]);
if($old_parent!=null) {
$this->set_has_children($old_parent);
}
}
}
} }
} }
private function set_child(int $parentID, int $childID)
public static function get_children(Image $image, int $omit = null): array
{ {
global $database; global $database;
$results = $database->get_all_iterable("SELECT * FROM images WHERE parent_id = :pid ", ["pid"=>$image->id]);
if ($database->get_row("SELECT 1 FROM images WHERE id = :cid", ["cid"=>$childID])) { $output = [];
$database->execute("UPDATE images SET parent_id = :pid WHERE id = :cid", ["cid"=>$childID, "pid"=>$parentID]); foreach ($results as $result) {
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", ["pid"=>$parentID]); if($result["id"]==$omit) {
continue;
}
$output[] = new Image($result);
} }
return $output;
} }
private function remove_parent(int $imageID) private function remove_parent(int $imageID)
@ -134,8 +166,23 @@ class Relationships extends Extension
if ($parentID) { if ($parentID) {
$database->execute("UPDATE images SET parent_id = NULL WHERE id = :iid", ["iid"=>$imageID]); $database->execute("UPDATE images SET parent_id = NULL WHERE id = :iid", ["iid"=>$imageID]);
$database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub) $this->set_has_children($parentID);
WHERE id = :pid", ["pid"=>$parentID]);
} }
} }
private function set_has_children(int $parent_id)
{
global $database;
// Doesn't work on pgsql
// $database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub)
// WHERE id = :pid", ["pid"=>$parentID]);
$database->execute(
"UPDATE images SET has_children = EXISTS (SELECT 1 FROM images WHERE parent_id = :pid) WHERE id = :pid",
["pid"=>$parent_id]);
}
} }

View File

@ -0,0 +1,192 @@
<?php
class RelationshipTest extends ShimmiePHPUnitTestCase
{
public function testSetParent()
{
$this->log_in_as_user();
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "pbx");
$image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx");
$image_id_3 = $this->post_image("tests/favicon.png", "pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertNull($image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", $image_id_1);
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1,$image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test changing to a different parent
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", $image_id_3);
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_3,$image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertTrue($image_3->has_children);
// Test setting parent to none
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__parent", "");
$this->click("Set");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertNull($image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id_1);
$this->delete_image($image_id_2);
$this->delete_image($image_id_3);
$this->log_out();
}
public function testSetParentByTag()
{
$this->log_in_as_user();
$image_id_1 = $this->post_image("tests/pbx_screenshot.jpg", "pbx");
$image_id_2 = $this->post_image("tests/bedroom_workshop.jpg", "pbx");
$image_id_3 = $this->post_image("tests/favicon.png", "pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertNull($image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertFalse($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test settings parent:#
$this->get_page("post/view/$image_id_2");
$this->assert_title("Image $image_id_2: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__tags", "pbx parent:$image_id_1");
$this->click("Set");
$this->assert_title("Image $image_id_2: pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1,$image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
// Test settings child:#
$this->get_page("post/view/$image_id_3");
$this->assert_title("Image $image_id_3: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__tags", "pbx child:$image_id_1");
$this->click("Set");
$this->assert_title("Image $image_id_3: pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertEquals($image_id_3,$image_1->parent_id);
$this->assertEquals($image_id_1,$image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertTrue($image_3->has_children);
// Test settings parent:none
$this->get_page("post/view/$image_id_1");
$this->assert_title("Image $image_id_1: pbx");
$this->markTestIncomplete();
$this->set_field("tag_edit__tags", "pbx parent:none");
$this->click("Set");
$this->assert_title("Image $image_id_1: pbx");
$image_1 = Image::by_id($image_id_1);
$image_2 = Image::by_id($image_id_2);
$image_3 = Image::by_id($image_id_3);
$this->assertNull($image_1->parent_id);
$this->assertEquals($image_id_1,$image_2->parent_id);
$this->assertNull($image_3->parent_id);
$this->assertTrue($image_1->has_children);
$this->assertFalse($image_2->has_children);
$this->assertFalse($image_3->has_children);
$this->log_out();
$this->log_in_as_admin();
$this->delete_image($image_id_1);
$this->delete_image($image_id_2);
$this->delete_image($image_id_3);
$this->log_out();
}
}