diff options
author | Bernhard Posselt <nukeawhale@gmail.com> | 2013-01-27 04:15:53 +0100 |
---|---|---|
committer | Bernhard Posselt <nukeawhale@gmail.com> | 2013-01-27 04:15:53 +0100 |
commit | ae7393db3d99a7ac223ae917129cccd9f49888e3 (patch) | |
tree | 7f54b72b0d01c38afd1378365a67e4f192922423 /db | |
parent | 483784caa38bd6131405ac474347a215584e30a5 (diff) |
merged the angularjs branch
Diffstat (limited to 'db')
-rw-r--r-- | db/collection.php | 34 | ||||
-rw-r--r-- | db/enclosure.php | 35 | ||||
-rw-r--r-- | db/feed.php | 75 | ||||
-rw-r--r-- | db/feedmapper.php | 263 | ||||
-rw-r--r-- | db/feedtype.php | 22 | ||||
-rw-r--r-- | db/feedtypes.php | 22 | ||||
-rw-r--r-- | db/folder.php | 76 | ||||
-rw-r--r-- | db/foldermapper.php | 198 | ||||
-rw-r--r-- | db/item.php | 168 | ||||
-rw-r--r-- | db/itemmapper.php | 422 | ||||
-rw-r--r-- | db/statusflag.php | 20 |
11 files changed, 1335 insertions, 0 deletions
diff --git a/db/collection.php b/db/collection.php new file mode 100644 index 000000000..30b926c00 --- /dev/null +++ b/db/collection.php @@ -0,0 +1,34 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class models a collection, which is either a feed or a folder. + */ +class Collection { + + private $id; + + public function __construct($id) { + $this->id = $id; + } + + public function getId() { + return $this->id; + } + + public function setId($id) { + $this->id = $id; + } + +} diff --git a/db/enclosure.php b/db/enclosure.php new file mode 100644 index 000000000..7eaddf158 --- /dev/null +++ b/db/enclosure.php @@ -0,0 +1,35 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + + +class Enclosure { + private $mimetype; + private $link; + + public function getMimeType() { + return $this->mimetype; + } + + public function setMimeType($mimetype) { + $this->mimetype = $mimetype; + } + + public function getLink() { + return $this->link; + } + + public function setLink($link) { + $this->link = $link; + } +} diff --git a/db/feed.php b/db/feed.php new file mode 100644 index 000000000..0f2e861b7 --- /dev/null +++ b/db/feed.php @@ -0,0 +1,75 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + + +/** + * This class models a feed. + */ +class Feed extends Collection { + + private $title; + private $url; + private $items; //array that contains all the items of the feed + private $favicon; + + // if $items = null, it means that feed has not been fetched yet + // if $id = null, it means that the feed has not been stored in the db yet + public function __construct($url, $title, $items = null, $id = null) { + $this->url = $url; + $this->title = $title; + if ($items !== null) { + $this->items = $items; + } + if ($id !== null) { + parent::__construct($id); + } + } + + public function getUrl() { + return $this->url; + } + + public function getTitle() { + return $this->title; + } + + public function setTitle($title) { + $this->title = $title; + } + + public function getFavicon() { + return $this->favicon; + } + + public function setFavicon($favicon) { + $this->favicon = $favicon; + } + + public function setItems($items) { + $this->items = $items; + } + + public function getItems() { + return $this->items; + } + + public function setFolderId($folderId){ + $this->folderId = $folderId; + } + + public function getFolderId(){ + return $this->folderId; + } + +} diff --git a/db/feedmapper.php b/db/feedmapper.php new file mode 100644 index 000000000..906ced069 --- /dev/null +++ b/db/feedmapper.php @@ -0,0 +1,263 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class maps a feed to an entry in the feeds table of the database. + */ +class FeedMapper { + + const tableName = '*PREFIX*news_feeds'; + private $userid; + + public function __construct($userid = null) { + if ($userid !== null) { + $this->userid = $userid; + } + else { + $this->userid = \OCP\USER::getUser(); + } + } + + /** + * @brief + * @param row a row from the feeds table of the database + * @returns an object of the class OCA\News\Feed + */ + public function fromRow($row) { + $url = $row['url']; + $title = $row['title']; + $id = $row['id']; + $folderid = $row['folder_id']; + $feed = new Feed($url, $title, null, $id); + $favicon = $row['favicon_link']; + $feed->setFavicon($favicon); + $feed->setFolderId($folderid); + + return $feed; + } + + /** + * @brief + * @returns + */ + public function findAll() { + $query = 'SELECT * FROM ' . self::tableName . ' WHERE user_id = ?'; + $stmt = \OCP\DB::prepare($query); + $result = $stmt->execute(array($this->userid)); + + $feeds = array(); + while($row = $result->fetchRow()){ + $feed = $this->fromRow($row); + array_push($feeds, $feed); + } + + return $feeds; + } + + /** + * @brief returns the number of feeds that a user has + * @returns the number of feeds that a user has + */ + public function feedCount() { + $query = 'SELECT COUNT(*) AS size FROM ' . self::tableName . ' WHERE user_id = ?'; + $stmt = \OCP\DB::prepare($query); + $result = $stmt->execute(array($this->userid))->fetchRow(); + return $result['size']; + } + + + /** + * @brief Retrieve a feed from the database + * @param id The id of the feed in the database table. + * @returns + */ + public function findById($id) { + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' WHERE id = ?'); + $result = $stmt->execute(array($id)); + if(!$row = $result->fetchRow()) + return null; + $feed = self::fromRow($row); + return $feed; + } + + /** + * @brief Retrieve all the feeds contained in the folder $folderid + * @param folderid The id of the folder in the database table. + * @returns a list of feeds + */ + public function findByFolderId($folderid) { + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' WHERE user_id = ? AND folder_id = ?'); + $result = $stmt->execute(array($this->userid, $folderid)); + $feeds = array(); + while ($row = $result->fetchRow()) { + $feed = self::fromRow($row); + $feeds[] = $feed; + } + return $feeds; + } + + + /** + * @brief Retrieve a feed and all its items from the database + * @param id The id of the feed in the database table. + * @returns an instance of OCA\News\Feed + */ + public function findWithItems($id) { + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' WHERE id = ?'); + $result = $stmt->execute(array($id)); + $row = $result->fetchRow(); + + $feed = self::fromRow($row); + $itemMapper = new ItemMapper(); + $items = $itemMapper->findById($id); + $feed->setItems($items); + + return $feed; + } + + /** + * @brief Find the id of a feed and all its items from the database + * @param url url of the feed + * @return id of the feed corresponding to the url passed as parameters + * null - if there is no such feed + */ + public function findIdFromUrl($url) { + $url_hash = md5($url); + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' WHERE url_hash = ?'); + $result = $stmt->execute(array($url_hash)); + $row = $result->fetchRow(); + $id = null; + if ($row != null) { + $id = $row['id']; + } + return $id; + } + + public function mostRecent() { + //FIXME: does something like SELECT TOP 1 * exists in pear/mdb2 ?? + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' ORDER BY lastmodified'); + $result = $stmt->execute(); + $row = $result->fetchRow(); + $id = null; + if ($row != null) { + $id = $row['id']; + } + return $id; + } + + /** + * @brief Save the feed and all its items into the database + * @param feed the feed to be saved + * @returns The id of the feed in the database table. + */ + //TODO: handle error case + public function save(Feed $feed, $folderid) { + $title = $feed->getTitle(); + $url = $feed->getUrl(); + $url_hash = md5($url); + + if(empty($title)) { + $l = \OC_L10N::get('news'); + $title = $l->t('no title'); + } + + $favicon = $feed->getFavicon(); + + //FIXME: Detect when feed contains already a database id + $feedid = $this->findIdFromUrl($url); + if ($feedid === null) { + $query = \OCP\DB::prepare(" + INSERT INTO " . self::tableName . + "(url, url_hash, title, favicon_link, folder_id, user_id, added, lastmodified) + VALUES (?, ?, ?, ?, ?, ?, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()) + "); + + $params=array( + $url, + $url_hash, + $title, + $favicon, + $folderid, + $this->userid + ); + $query->execute($params); + + $feedid = \OCP\DB::insertid(self::tableName); + } + else { + //update the db. it needs to be done, since it might be the first save after a full fetch + $stmt = \OCP\DB::prepare(' + UPDATE ' . self::tableName . + ' SET favicon_link = ? , lastmodified = UNIX_TIMESTAMP() , folder_id = ? + WHERE id = ? + '); + + $params=array( + $favicon, + $folderid, + $feedid + ); + $stmt->execute($params); + } + $feed->setId($feedid); + + $itemMapper = new ItemMapper(); + + $items = $feed->getItems(); + if ($items !== null) { + foreach($items as $item) { + $itemMapper->save($item, $feedid); + } + } + + return $feedid; + } + + + public function deleteById($id) { + if ($id == null) { + return false; + } + $stmt = \OCP\DB::prepare('DELETE FROM ' . self::tableName .' WHERE id = ? AND user_id = ?'); + + $result = $stmt->execute(array($id, $this->userid)); + + $itemMapper = new ItemMapper(); + //TODO: handle the value that the execute returns + $itemMapper->deleteAll($id); + + return true; + } + + public function delete(Feed $feed) { + $id = $feed->getId(); + return deleteById($id); + } + + public function deleteAll($folderid) { + if ($folderid == null) { + return false; + } + + $stmt = \OCP\DB::prepare('SELECT id FROM ' . self::tableName . ' WHERE folder_id = ? AND user_id = ?'); + + $result = $stmt->execute(array($folderid, $this->userid)); + while ($row = $result->fetchRow()) { + if(!self::deleteById($row['id'])) + return false; + } + + return true; + } +} diff --git a/db/feedtype.php b/db/feedtype.php new file mode 100644 index 000000000..d330a5b2a --- /dev/null +++ b/db/feedtype.php @@ -0,0 +1,22 @@ +<?php +/** +* ownCloud - News app +* +* @author Bernhard Posselt +* Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + + +class FeedType { + const FEED = 0; + const FOLDER = 1; + const STARRED = 2; + const SUBSCRIPTIONS = 3; + const SHARED = 4; +};
\ No newline at end of file diff --git a/db/feedtypes.php b/db/feedtypes.php new file mode 100644 index 000000000..d330a5b2a --- /dev/null +++ b/db/feedtypes.php @@ -0,0 +1,22 @@ +<?php +/** +* ownCloud - News app +* +* @author Bernhard Posselt +* Copyright (c) 2012 - Bernhard Posselt <nukeawhale@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + + +class FeedType { + const FEED = 0; + const FOLDER = 1; + const STARRED = 2; + const SUBSCRIPTIONS = 3; + const SHARED = 4; +};
\ No newline at end of file diff --git a/db/folder.php b/db/folder.php new file mode 100644 index 000000000..2e3c96a7c --- /dev/null +++ b/db/folder.php @@ -0,0 +1,76 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class models a folder that contains feeds. + */ +class Folder extends Collection { + + private $name; + private $children; + private $parent; + private $opened; + + public function __construct($name, $id = null, Collection $parent = null) { + $this->name = $name; + if ($id !== null) { + parent::__construct($id); + } + $this->children = array(); + if ($parent !== null) { + $this->parent = $parent; + } + if($this->opened === null){ + $this->opened = true; + } + } + + public function getName() { + return $this->name; + } + + public function setName($name) { + $this->name = $name; + } + + public function getOpened() { + return $this->opened; + } + + public function setOpened($opened) { + $this->opened = $opened; + } + + public function getParentId() { + if ($this->parent === null) { + return 0; + } + return $this->parent->getId(); + } + + public function addChild(Collection $child) { + $this->children[] = $child; + } + + public function addChildren($children) { + $this->children = $children; + } + + public function getChildren() { + return $this->children; + } + + + +}
\ No newline at end of file diff --git a/db/foldermapper.php b/db/foldermapper.php new file mode 100644 index 000000000..5d7145176 --- /dev/null +++ b/db/foldermapper.php @@ -0,0 +1,198 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class maps a feed to an entry in the feeds table of the database. + */ +class FolderMapper { + + const tableName = '*PREFIX*news_folders'; + + private $userid; + + public function __construct($userid = null) { + if ($userid !== null) { + $this->userid = $userid; + } + else { + $this->userid = \OCP\USER::getUser(); + } + } + + + /** + * @brief Returns the forest (list of trees) of folders children of $parentid + * @param + * @returns + */ + public function childrenOf($parentid) { + $folderlist = array(); + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . + ' WHERE user_id = ? AND parent_id = ?'); + $result = $stmt->execute(array($this->userid, $parentid)); + + while( $row = $result->fetchRow()) { + $folderid = $row['id']; + $folder = new Folder($row['name'], $folderid); + $folder->setOpened($row['opened']); + $children = self::childrenOf($folderid); + $folder->addChildren($children); + $folderlist[] = $folder; + } + + return $folderlist; + } + + /** + * @brief Returns the forest (list of trees) of folders children of $parentid, + * including the feeds that they contain + * @param + * @returns + */ + public function childrenOfWithFeeds($parentid) { + + $feedmapper = new FeedMapper(); + $collectionlist = $feedmapper->findByFolderId($parentid); + + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . + ' WHERE user_id = ? AND parent_id = ?'); + $result = $stmt->execute(array($this->userid, $parentid)); + + while( $row = $result->fetchRow()) { + $folderid = $row['id']; + $folder = new Folder($row['name'], $folderid); + $folder->setOpened($row['opened']); + $children = self::childrenOfWithFeeds($folderid); + $folder->addChildren($children); + $collectionlist[] = $folder; + } + + return $collectionlist; + } + + + /** + * This is being used for consistency + */ + public function findById($id){ + return $this->find($id); + } + + + /** + * @brief Retrieve a folder from the database + * @param id The id of the folder in the database table. + * @returns an instance of OC_News_Folder + */ + public function find($id) { + $stmt = \OCP\DB::prepare('SELECT * + FROM ' . self::tableName . + ' WHERE user_id = ? AND id = ?'); + $result = $stmt->execute(array($this->userid, $id)); + + $row = $result->fetchRow(); + $folder = new Folder($row['name'], $row['id']); + $folder->setOpened($row['opened']); + + return $folder; + } + + /** + * @brief Store the folder and all its feeds into the database + * @param folder the folder to be saved + * @returns The id of the folder in the database table. + */ + public function save(Folder $folder) { + $query = \OCP\DB::prepare(' + INSERT INTO ' . self::tableName . + '(name, parent_id, user_id, opened) + VALUES (?, ?, ?, ?) + '); + + $name = $folder->getName(); + + if(empty($name)) { + $l = \OC_L10N::get('news'); + $name = $l->t('no name'); + } + + $parentid = $folder->getParentId(); + + $params=array( + $name, + $parentid, + $this->userid, + $folder->getOpened() + ); + $query->execute($params); + $folderid = \OCP\DB::insertid(self::tableName); + + $folder->setId($folderid); + return $folderid; + } + + + /** + * @brief Updates the folder + * @param folder the folder to be updated + */ + public function update(Folder $folder) { + $query = \OCP\DB::prepare('UPDATE ' . self::tableName + . ' SET name = ?, opened = ?' . ' WHERE id = ?'); + + $params = array($folder->getName(), $folder->getOpened(), $folder->getId()); + $query->execute($params); + return true; + } + + /** + * @brief Delete the folder and all its feeds from the database + * @param folder the folder to be deleted (an instance of OCA\News\Folder) + * @returns true if the folder has been deleted, false if an error occurred + */ + public function delete(Folder $folder) { + $folderid = $folder->getId(); + return deleteById(folderid); + } + + /** + * @brief Delete the folder and all its feeds from the database + * @param folder the folder to be deleted (an instance of OCA\News\Folder) + * @returns true if the folder has been deleted, false if an error occurred + */ + public function deleteById($folderid) { + if ($folderid == null) { + return false; + } + + // delete child folders + $stmt = \OCP\DB::prepare('SELECT id FROM ' . self::tableName .' WHERE parent_id = ? AND user_id = ?'); + $result = $stmt->execute(array($folderid, $this->userid)); + while ($row = $result->fetchRow()) { + if (!self::deleteById($row['id'])) + return false; + } + + $stmt = \OCP\DB::prepare('DELETE FROM ' . self::tableName .' WHERE id = ? AND user_id = ?'); + $result = $stmt->execute(array($folderid, $this->userid)); + + $feedMapper = new FeedMapper($this->userid); + //TODO: handle the value that the execute returns + if(!$feedMapper->deleteAll($folderid)) + return false; + + return true; + } + +}
\ No newline at end of file diff --git a/db/item.php b/db/item.php new file mode 100644 index 000000000..bda17204e --- /dev/null +++ b/db/item.php @@ -0,0 +1,168 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class models an item. + * + * It encapsulate a SimplePie_Item object and adds a status flag to it + */ +class Item { + + private $url; + private $title; + private $guid; + private $body; + private $status; //a bit-field set with status flags + private $id; //id of the item in the database table + private $author; + private $date; //date is stored in the Unix format + private $feedTitle; + private $enclosure; // Enclosure object containing media attachment information + + public function __construct($url, $title, $guid, $body, $id = null) { + $this->title = $title; + $this->url = $url; + $this->guid = $guid; + $this->body = $body; + $this->enclosure = false; + if ($id == null) { + $this->status |= StatusFlag::UNREAD; + } + else { + $this->id = $id; + } + } + + public function getFeedId() { + return $this->feedId; + } + + public function setFeedId($feedId) { + $this->feedId = $feedId; + } + + public function getGuid() { + return $this->guid; + } + + public function setGuid($guid) { + $this->guid = $guid; + } + + public function getId() { + return $this->id; + } + + public function setId($id) { + $this->id = $id; + } + + public function setRead() { + $this->status &= ~StatusFlag::UNREAD; + } + + public function setUnread() { + $this->status |= StatusFlag::UNREAD; + } + + public function isRead() { + return !($this->status & StatusFlag::UNREAD); + } + + public function setImportant() { + $this->status |= StatusFlag::IMPORTANT; + } + + public function setUnimportant() { + $this->status &= ~StatusFlag::IMPORTANT; + } + + public function isImportant() { + return ($this->status & StatusFlag::IMPORTANT); + } + + /** + * NOTE: this is needed to store items in the database, otherwise + * the status of an item should be retrieved with methods: isRead(), isImportant(), ... + */ + public function getStatus() { + return $this->status; + } + + public function setStatus($status) { + $this->status = $status; + } + + /* change the following method with set/get magic methods + * http://www.php.net/manual/en/language.oop5.overloading.php#object.get + */ + + public function getTitle() { + return $this->title; + } + + public function setTitle($title) { + $this->title = $title; + } + + public function getFeedTitle() { + return $this->feedTitle; + } + + public function setFeedTitle($feedtitle) { + $this->feedTitle = $feedtitle; + } + + public function getUrl() { + return $this->url; + } + + public function setUrl($url) { + $this->url = $url; + } + + public function getBody() { + return $this->body; + } + + public function setBody($body) { + $this->body = $body; + } + + public function getAuthor() { + return $this->author; + } + + public function setAuthor($author) { + $this->author = $author; + } + + public function getDate() { + return $this->date; + } + + //TODO: check if the parameter is in the Unix format + public function setDate($date) { + $this->date = $date; + } + + public function getEnclosure() { + return $this->enclosure; + } + + public function setEnclosure(Enclosure $enclosure) { + $this->enclosure = $enclosure; + } +} + diff --git a/db/itemmapper.php b/db/itemmapper.php new file mode 100644 index 000000000..3399e2e03 --- /dev/null +++ b/db/itemmapper.php @@ -0,0 +1,422 @@ +<?php +/** +* ownCloud - News app +* +* @author Alessandro Cosentino +* Copyright (c) 2012 - Alessandro Cosentino <cosenal@gmail.com> +* +* This file is licensed under the Affero General Public License version 3 or later. +* See the COPYING-README file +* +*/ + +namespace OCA\News; + +/** + * This class maps an item to a row of the items table in the database. + * It follows the Data Mapper pattern (see http://martinfowler.com/eaaCatalog/dataMapper.html). + */ +class ItemMapper { + + const tableName = '*PREFIX*news_items'; + private $userid; + + public function __construct($userid = null) { + if ($userid !== null) { + $this->userid = $userid; + } + else { + $this->userid = \OCP\USER::getUser(); + } + } + + /** + * @brief + * @param row a row from the items table of the database + * @returns an object of the class OC_News_Item + */ + public function fromRow($row) { + $url = $row['url']; + $title = $row['title']; + $guid = $row['guid']; + $body = $row['body']; + $id = $row['id']; + + $item = new Item($url, $title, $guid, $body, $id); + $item->setStatus($row['status']); + $item->setAuthor($row['author']); + $item->setFeedId($row['feed_id']); + $item->setDate(Utils::dbtimestampToUnixtime($row['pub_date'])); + + $feedmapper = new FeedMapper($this->userid); + $feed = $feedmapper->findById($row['feed_id']); + $item->setFeedTitle($feed->getTitle()); + + if($row['enclosure_mime'] !== null && $row['enclosure_link'] !== null) { + $enclosure = new Enclosure(); + $enclosure->setMimeType($row['enclosure_mime']); + $enclosure->setLink($row['enclosure_link']); + $item->setEnclosure($enclosure); + } + + return $item; + } + + /** + * @brief Retrieve all the item corresponding to a feed from the database + * @param feedid The id of the feed in the database table. + */ + public function findByFeedId($feedid) { + $stmt = \OCP\DB::prepare('SELECT * FROM ' . self::tableName . ' WHERE feed_id = ? ORDER BY pub_date DESC'); + $result = $stmt->execute(array($feedid)); + + $items = array(); + while ($row |