1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00
This commit is contained in:
Laurent Cozic 2017-06-04 18:38:31 +01:00
parent e2012ed833
commit 0d9e52956c
10 changed files with 203 additions and 127 deletions

View File

@ -3,5 +3,14 @@
# Example to test just one method of a test unit:
# php phpunit-5.7.20.phar --filter testConflict ChangeTest tests/Model/ChangeTest.php --bootstrap vendor/autoload.php tests/Model/
# php5.6 phpunit-5.7.20.phar --bootstrap vendor/autoload.php tests/Controller/
echo '============================================================================================='
echo 'Testing controllers....'
echo '============================================================================================='
php5.6 phpunit-5.7.20.phar --bootstrap vendor/autoload.php tests/Controller/
echo ""
echo '============================================================================================='
echo 'Testing models....'
echo '============================================================================================='
php5.6 phpunit-5.7.20.phar --bootstrap vendor/autoload.php tests/Model/

View File

@ -0,0 +1,103 @@
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Controller\ApiController;
use AppBundle\Model\Tag;
use AppBundle\Model\BaseItem;
use AppBundle\Exception\ValidationException;
class TagsController extends ApiController {
/**
* @Route("/tags")
*/
public function allAction(Request $request) {
if ($request->isMethod('POST')) {
$tag = new Tag();
$tag->fromPublicArray($request->request->all());
$tag->owner_id = $this->user()->id;
$tag->save();
return static::successResponse($tag->toPublicArray());
}
throw new MethodNotAllowedException();
}
/**
* @Route("/tags/{id}")
*/
public function oneAction($id, Request $request) {
$tag = Tag::find(Tag::unhex($id));
if (!$tag && !$request->isMethod('PUT')) throw new NotFoundException();
if ($request->isMethod('GET')) {
return static::successResponse($tag);
}
$query = $request->query->all();
if ($tag && isset($query['rev_id'])) $tag->revId = $query['rev_id'];
if ($request->isMethod('PUT')) {
$isNew = !$tag;
if ($isNew) $tag = new Tag();
$data = Tag::filter($this->putParameters());
$tag->fromPublicArray($data);
$tag->id = Tag::unhex($id);
$tag->owner_id = $this->user()->id;
$tag->setIsNew($isNew);
$tag->save();
return static::successResponse($tag);
}
if ($request->isMethod('PATCH')) {
$tag->fromPublicArray($this->patchParameters());
$tag->save();
return static::successResponse($tag);
}
if ($request->isMethod('DELETE')) {
$tag->delete();
return static::successResponse();
}
throw new MethodNotAllowedException();
}
/**
* @Route("/tags/{id}/items/{itemId}")
*/
public function linkedItemAction($id, $itemId = null, Request $request = null) {
$tag = Tag::byId(Tag::unhex($id));
if (!$tag) throw new NotFoundException();
if ($request->isMethod('GET')) {
return static::successResponse($tag->items());
}
if ($request->isMethod('POST')) {
$item = $request->request->all();
if (!isset($item['id'])) throw new ValidationException('Item "id" parameter is missing');
$itemId = $item['id'];
$item = BaseItem::anyById(BaseItem::unhex($itemId));
if (!$item) throw new ValidationException('Item not found: ' . $itemId);
$tag->add($item);
return static::successResponse($tag);
}
if ($request->isMethod('DELETE')) {
$tag->remove(BaseItem::unhex($itemId));
return static::successResponse($tag);
}
throw new MethodNotAllowedException();
}
}

View File

@ -41,5 +41,12 @@ class BaseItem extends BaseModel {
throw new \Exception('Unsupported item type: ' . $itemTypeId);
}
// Use only if type of item is unknown
static public function anyById($itemId) {
$folder = Folder::find($itemId);
if ($folder) return $folder;
return Note::find($itemId);
}
}

View File

@ -185,6 +185,7 @@ class BaseModel extends \Illuminate\Database\Eloquent\Model {
if (!empty($output['client_id'])) $output['client_id'] = self::hex($output['client_id']);
if (!empty($output['item_id'])) $output['item_id'] = self::hex($output['item_id']);
if (!empty($output['user_id'])) $output['user_id'] = self::hex($output['user_id']);
if (!empty($output['tag_id'])) $output['tag_id'] = self::hex($output['tag_id']);
foreach ($output as $k => $v) {
if (isset(static::$enums[$k])) {

View File

@ -2,48 +2,22 @@
namespace AppBundle\Model;
use AppBundle\Exception\ForbiddenException;
class Tag extends BaseItem {
// A star has the exact same behaviour as a tag, except
// it might be diplayed differently.
static private $starTag_ = null;
static public function starTag($ownerId) {
if (self::$starTag_) return self::$starTag_;
$t = Tag::where('internal', '=', 1)
->where('title', '=', 'star')
->first();
if (!$t) {
$t = new Tag();
$t->title = 'star';
$t->internal = 1;
$t->owner_id = $ownerId;
$t->save();
}
self::$starTag_ = $t;
return self::$starTag_;
}
static public function star($item) {
self::starTag($item->owner_id)->add($item);
}
static public function unstar($item) {
self::starTag($item->owner_id)->remove($item);
}
static public function isStarred($item) {
return self::starTag($item->owner_id)->includes($item);
}
static public function starredItems($ownerId) {
return self::starTag($ownerId)->items();
}
static protected $fields = array(
'id' => null,
'title' => null,
'owner_id' => null,
'created_time' => null,
'updated_time' => null,
);
public function add($item) {
if ($this->includes($item)) return;
if ($this->includes($item->id)) return;
if ($item->owner_id != $this->owner_id) throw new ForbiddenException();
$t = new Tagged_item();
$t->tag_id = $this->id;
@ -52,27 +26,19 @@ class Tag extends BaseItem {
$t->save();
}
public function includes($item) {
return !!Tagged_item::where('item_type', '=', $item->itemTypeId())
->where('item_id', '=', $item->id)
public function includes($itemId) {
return !!Tagged_item::where('item_id', '=', $itemId)
->where('tag_id', '=', $this->id)
->first();
}
public function remove($item) {
Tagged_item::where('item_type', '=', $item->itemTypeId())
->where('item_id', '=', $item->id)
->delete();
public function remove($itemId) {
return Tagged_item::where('tag_id', '=', $this->id)->where('item_id', '=', $itemId)->delete();
}
// TODO: retrieve items in one SQL query
public function items() {
$output = array();
$taggedItems = Tagged_item::where('tag_id', '=', $this->id)->get();
foreach ($taggedItems as $taggedItem) {
$item = BaseItem::byTypeAndId($taggedItem->item_type, $taggedItem->item_id);
$output[] = $item;
}
return $output;
return Tagged_item::where('tag_id', '=', $this->id)->get();
}
}

View File

@ -4,4 +4,13 @@ namespace AppBundle\Model;
class Tagged_item extends BaseModel {
static protected $fields = array(
'id' => null,
'tag_id' => null,
'item_id' => null,
'item_type' => null,
'created_time' => null,
'updated_time' => null,
);
}

View File

@ -38,11 +38,8 @@ CREATE TABLE `tags` (
`id` binary(16) NOT NULL,
`title` varchar(1024) NOT NULL default '',
`owner_id` binary(16) NOT NULL,
`internal` tinyint(1) NOT NULL default '0',
`created_time` int(11) NOT NULL default '0',
`updated_time` int(11) NOT NULL default '0',
`is_encrypted` tinyint(1) NOT NULL default '0',
`encryption_method` int(11) NOT NULL default '0',
PRIMARY KEY (`id`)
) CHARACTER SET=utf8;

View File

@ -45,6 +45,7 @@ class BaseControllerTestCase extends WebTestCase {
'error' => $e->getMessage(),
'code' => $e->getCode(),
'type' => get_class($e),
'trace' => $e->getTraceAsString(),
);
}
return $output;

View File

@ -0,0 +1,54 @@
<?php
require_once dirname(dirname(__FILE__)) . '/setup.php';
use AppBundle\Model\Tag;
use AppBundle\Model\Folder;
use AppBundle\Model\Note;
class TagsControllerTest extends BaseControllerTestCase {
public function setUp() {
parent::setUp();
Tag::truncate();
Note::truncate();
Folder::truncate();
}
public function testCreate() {
$this->loadSession(1, 1);
$t = $this->request('POST', '/tags', null, array('title' => 'my tag'));
$this->assertEquals('my tag', $t['title']);
}
public function testTagNote() {
$this->loadSession(1, 1);
$tag = $this->request('POST', '/tags', null, array('title' => 'my tag'));
$note = $this->request('POST', '/notes', null, array('title' => 'my note'));
$this->request('POST', '/tags/' . $tag['id'] . '/items', null, array('id' => $note['id']));
$items = $this->request('GET', '/tags/' . $tag['id'] . '/items');
$this->assertEquals(1, count($items));
$this->assertEquals('note', $items[0]['item_type']);
$this->assertEquals($note['id'], $items[0]['item_id']);
$this->assertEquals($tag['id'], $items[0]['tag_id']);
$folder = $this->request('POST', '/folders', null, array('title' => 'my folder'));
$this->request('POST', '/tags/' . $tag['id'] . '/items', null, array('id' => $folder['id']));
$items = $this->request('GET', '/tags/' . $tag['id'] . '/items');
$this->assertEquals(2, count($items));
$this->assertEquals('folder', $items[1]['item_type']);
$this->assertEquals($folder['id'], $items[1]['item_id']);
$this->assertEquals($tag['id'], $items[1]['tag_id']);
$this->request('DELETE', '/tags/' . $tag['id'] . '/items/' . $note['id']);
$items = $this->request('GET', '/tags/' . $tag['id'] . '/items');
$this->assertEquals(1, count($items));
$this->assertEquals('folder', $items[0]['item_type']);
}
}

View File

@ -1,71 +0,0 @@
<?php
require_once dirname(dirname(__FILE__)) . '/setup.php';
use AppBundle\Model\Note;
use AppBundle\Model\Tag;
class TagTest extends BaseTestCase {
public function setUp() {
parent::setUp();
}
public function testTagging() {
$note = new Note();
$note->save();
$tag = new Tag();
$tag->owner_id = $this->userId();
$tag->save();
$this->assertFalse($tag->includes($note));
$tag->add($note);
$items = $tag->items();
$this->assertEquals(1, count($items));
$tag->add($note);
$items = $tag->items();
$this->assertEquals(1, count($items));
$note2 = new Note();
$note2->save();
$tag->add($note2);
$items = $tag->items();
$this->assertEquals(2, count($items));
$this->assertEquals($note->id, $items[0]->id);
$this->assertEquals($note2->id, $items[1]->id);
$this->assertTrue($tag->includes($note));
$this->assertTrue($tag->includes($note2));
$tag->remove($note);
$items = $tag->items();
$this->assertEquals(1, count($items));
$tag->remove($note2);
$items = $tag->items();
$this->assertEquals(0, count($items));
}
public function testStarring() {
$note = new Note();
$note->owner_id = $this->userId();
$note->save();
$this->assertFalse(Tag::isStarred($note));
Tag::star($note);
$this->assertTrue(Tag::isStarred($note));
$this->assertEquals(1, count(Tag::starredItems($this->userId())));
Tag::star($note);
$this->assertEquals(1, count(Tag::starredItems($this->userId())));
Tag::unstar($note);
$this->assertFalse(Tag::isStarred($note));
}
}