public function getLastId($column = '') {
return $this->getHandle()->lastInsertId($column);
}
+
+ public function retrieveAllTags() {
+ $sql = "SELECT * FROM tags";
+ $query = $this->executeQuery($sql, array());
+ $tags = $query->fetchAll();
+
+ return $tags;
+ }
+
+ public function retrieveTag($id) {
+ $tag = NULL;
+ $sql = "SELECT * FROM tags WHERE id=?";
+ $params = array(intval($id));
+ $query = $this->executeQuery($sql, $params);
+ $tag = $query->fetchAll();
+
+ return isset($tag[0]) ? $tag[0] : null;
+ }
+
+ public function retrieveEntriesByTag($tag_id) {
+ $sql =
+ "SELECT * FROM entries
+ LEFT JOIN tags_entries ON tags_entries.entry_id=entries.id
+ WHERE tags_entries.tag_id = ?";
+ $query = $this->executeQuery($sql, array($tag_id));
+ $entries = $query->fetchAll();
+
+ return $entries;
+ }
+
+ public function retrieveTagsByEntry($entry_id) {
+ $sql =
+ "SELECT * FROM tags
+ LEFT JOIN tags_entries ON tags_entries.tag_id=tags.id
+ WHERE tags_entries.entry_id = ?";
+ $query = $this->executeQuery($sql, array($entry_id));
+ $tags = $query->fetchAll();
+
+ return $tags;
+ }
+
+ public function removeTagForEntry($entry_id, $tag_id) {
+ $sql_action = "DELETE FROM tags_entries WHERE tag_id=? AND entry_id=?";
+ $params_action = array($tag_id, $entry_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ return $query;
+ }
+
+ public function retrieveTagByValue($value) {
+ $tag = NULL;
+ $sql = "SELECT * FROM tags WHERE value=?";
+ $params = array($value);
+ $query = $this->executeQuery($sql, $params);
+ $tag = $query->fetchAll();
+
+ return isset($tag[0]) ? $tag[0] : null;
+ }
+
+ public function createTag($value) {
+ $sql_action = 'INSERT INTO tags ( value ) VALUES (?)';
+ $params_action = array($value);
+ $query = $this->executeQuery($sql_action, $params_action);
+ return $query;
+ }
+
+ public function setTagToEntry($tag_id, $entry_id) {
+ $sql_action = 'INSERT INTO tags_entries ( tag_id, entry_id ) VALUES (?, ?)';
+ $params_action = array($tag_id, $entry_id);
+ $query = $this->executeQuery($sql_action, $params_action);
+ return $query;
+ }
}
Tools::redirect();
}
break;
+ case 'add_tag' :
+ $tags = explode(',', $_POST['value']);
+ $entry_id = $_POST['entry_id'];
+ foreach($tags as $key => $tag_value) {
+ $value = trim($tag_value);
+ $tag = $this->store->retrieveTagByValue($value);
+
+ if (is_null($tag)) {
+ # we create the tag
+ $tag = $this->store->createTag($value);
+ $sequence = '';
+ if (STORAGE == 'postgres') {
+ $sequence = 'tags_id_seq';
+ }
+ $tag_id = $this->store->getLastId($sequence);
+ }
+ else {
+ $tag_id = $tag['id'];
+ }
+
+ # we assign the tag to the article
+ $this->store->setTagToEntry($tag_id, $entry_id);
+ }
+ Tools::redirect();
+ break;
+ case 'remove_tag' :
+ $tag_id = $_GET['tag_id'];
+ $this->store->removeTagForEntry($id, $tag_id);
+ Tools::redirect();
+ break;
default:
break;
}
);
Tools::logm('config view');
break;
+ case 'edit-tags':
+ # tags
+ $tags = $this->store->retrieveTagsByEntry($id);
+ $tpl_vars = array(
+ 'entry_id' => $id,
+ 'tags' => $tags,
+ );
+ break;
+ case 'tag':
+ $entries = $this->store->retrieveEntriesByTag($id);
+ $tag = $this->store->retrieveTag($id);
+ $tpl_vars = array(
+ 'tag' => $tag,
+ 'entries' => $entries,
+ );
+ break;
+ case 'tags':
+ $token = $this->user->getConfigValue('token');
+ $tags = $this->store->retrieveAllTags();
+ $tpl_vars = array(
+ 'token' => $token,
+ 'user_id' => $this->user->getId(),
+ 'tags' => $tags,
+ );
+ break;
case 'view':
$entry = $this->store->retrieveOneById($id, $this->user->getId());
if ($entry != NULL) {
# flattr checking
$flattr = new FlattrItem();
- $flattr->checkItem($entry['url'],$entry['id']);
+ $flattr->checkItem($entry['url'], $entry['id']);
+
+ # tags
+ $tags = $this->store->retrieveTagsByEntry($entry['id']);
$tpl_vars = array(
- 'entry' => $entry,
- 'content' => $content,
- 'flattr' => $flattr
+ 'entry' => $entry,
+ 'content' => $content,
+ 'flattr' => $flattr,
+ 'tags' => $tags
);
}
else {
$_SESSION['poche_user']->setConfig($currentConfig);
}
- public function generateFeeds($token, $user_id, $type = 'home')
+ public function generateFeeds($token, $user_id, $tag_id, $type = 'home')
{
- $allowed_types = array('home', 'fav', 'archive');
+ $allowed_types = array('home', 'fav', 'archive', 'tag');
$config = $this->store->getConfigUser($user_id);
if (!in_array($type, $allowed_types) ||
$feed->setChannelElement('updated', date(DATE_RSS , time()));
$feed->setChannelElement('author', 'poche');
- $entries = $this->store->getEntriesByView($type, $user_id);
+ if ($type == 'tag') {
+ $entries = $this->store->retrieveEntriesByTag($tag_id);
+ }
+ else {
+ $entries = $this->store->getEntriesByView($type, $user_id);
+ }
+
if (count($entries) > 0) {
foreach ($entries as $entry) {
$newItem = $feed->createNewItem();
public static function getTplFile($view)
{
- $default_tpl = 'home.twig';
-
- switch ($view) {
- case 'install':
- $tpl_file = 'install.twig';
- break;
- case 'import';
- $tpl_file = 'import.twig';
- break;
- case 'export':
- $tpl_file = 'export.twig';
- break;
- case 'config':
- $tpl_file = 'config.twig';
- break;
- case 'view':
- $tpl_file = 'view.twig';
- break;
-
- case 'login':
- $tpl_file = 'login.twig';
- break;
-
- case 'error':
- $tpl_file = 'error.twig';
- break;
-
- default:
- $tpl_file = $default_tpl;
- break;
+ $views = array(
+ 'install', 'import', 'export', 'config', 'tags',
+ 'edit-tags', 'view', 'login', 'error', 'tag'
+ );
+
+ if (in_array($view, $views)) {
+ return $view . '.twig';
}
-
- return $tpl_file;
+
+ return 'home.twig';
}
public static function getFile($url)
$poche->generateToken();
}
else {
- $poche->generateFeeds($_GET['token'], $_GET['user_id'], $_GET['type']);
+ $tag_id = (isset($_GET['tag_id']) ? intval($_GET['tag_id']) : 0);
+ $poche->generateFeeds($_GET['token'], $_GET['user_id'], $tag_id, $_GET['type']);
}
}
`name` varchar(255) NOT NULL,
`value` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE tags (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `value` varchar(255) NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE tags_entries (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `entry_id` int(11) NOT NULL,
+ `tag_id` int(11) NOT NULL,
+ FOREIGN KEY(entry_id) REFERENCES entries(id) ON DELETE CASCADE,
+ FOREIGN KEY(tag_id) REFERENCES tags(id) ON DELETE CASCADE,
+ PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
\ No newline at end of file
user_id integer NOT NULL,
name varchar(255) NOT NULL,
value varchar(255) NOT NULL
-);
\ No newline at end of file
+);
+
+CREATE TABLE tags (
+ id bigserial primary key,
+ value varchar(255) NOT NULL
+);
+
+CREATE TABLE tags_entries (
+ id bigserial primary key,
+ entry_id integer NOT NULL,
+ tag_id integer NOT NULL
+)
\ No newline at end of file
<li><a href="./" {% if view == 'home' %}class="current"{% endif %}>{% trans "home" %}</a></li>
<li><a href="./?view=fav" {% if view == 'fav' %}class="current"{% endif %}>{% trans "favorites" %}</a></li>
<li><a href="./?view=archive" {% if view == 'archive' %}class="current"{% endif %}>{% trans "archive" %}</a></li>
+ <li><a href="./?view=tags" {% if view == 'tags' %}class="current"{% endif %}>{% trans "tags" %}</a></li>
<li><a href="./?view=config" {% if view == 'config' %}class="current"{% endif %}>{% trans "config" %}</a></li>
<li><a href="./?logout" title="{% trans "logout" %}">{% trans "logout" %}</a></li>
</ul>
\ No newline at end of file
text-decoration: none;
}
+#article .tags {
+ font-size: 0.8em;
+ color: #888;
+ padding-bottom: 5px;
+}
+
.backhome {
display: inline;
}
--- /dev/null
+{% extends "layout.twig" %}
+{% block title %}edit tags{% endblock %}
+{% block menu %}
+{% include '_menu.twig' %}
+{% endblock %}
+{% block content %}
+{% if tags is empty %}
+no tags
+{% endif %}
+<ul>
+{% for tag in tags %}<li>{{ tag.value }} <a href="./?action=remove_tag&tag_id={{ tag.id }}&id={{ entry_id }}">✘</a></li>{% endfor %}
+</ul>
+<form method="post" action="./?action=add_tag">
+ <label for="value">New tags: </label><input type="text" id="value" name="value" required="required" />
+ <p>{% trans "you can type several tags, separated by comma" %}</p>
+ <input type="hidden" name="entry_id" value="{{ entry_id }}" />
+ <input type="submit" value="add tags" />
+</form>
+<a href="./?view=view&id={{ entry_id }}">{% trans "back to the article" %}</a>
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% extends "layout.twig" %}
+{% block title %}tag {% endblock %}
+{% block menu %}
+{% include '_menu.twig' %}
+{% endblock %}
+{% block content %}
+ <h3>{% trans "Tag" %} {{ tag.value }}</h3>
+ {% if entries is empty %}
+ <div class="messages warning"><p>{% trans "No link available here!" %}</p></div>
+ {% else %}
+ {% block pager %}
+ {% if nb_results > 1 %}
+ <div class="results">
+ <div class="nb-results">{{ nb_results }} {% trans "results" %}</div>
+ {{ page_links | raw }}
+ </div>
+ {% endif %}
+ {% endblock %}
+ {% for entry in entries %}
+ <div id="entry-{{ entry.id|e }}" class="entrie">
+ <h2><a href="index.php?view=view&id={{ entry.id|e }}">{{ entry.title|raw }}</a></h2>
+ <ul class="tools">
+ <li><a title="{% trans "toggle mark as read" %}" class="tool {% if entry.is_read == 0 %}archive-off{% else %}archive{% endif %}" href="./?action=toggle_archive&id={{ entry.id|e }}"><span>{% trans "toggle mark as read" %}</span></a></li>
+ <li><a title="{% trans "toggle favorite" %}" class="tool {% if entry.is_fav == 0 %}fav-off{% else %}fav{% endif %}" href="./?action=toggle_fav&id={{ entry.id|e }}"><span>{% trans "toggle favorite" %}</span></a></li>
+ <li><a title="{% trans "delete" %}" class="tool delete" href="./?action=delete&id={{ entry.id|e }}"><span>{% trans "delete" %}</span></a></li>
+ <li><a href="{{ entry.url|e }}" target="_blank" title="{% trans "original" %} : {{ entry.title|e }}" class="tool link"><span>{{ entry.url | e | getDomain }}</span></a></li>
+ <li><a target="_blank" title="{% trans "estimated reading time:" %} {{ entry.content| getReadingTime }} min" class="reading-time"><span>{{ entry.content| getReadingTime }} min</span></a></li>
+ </ul>
+ <p>{{ entry.content|striptags|slice(0, 300) }}...</p>
+ </div>
+ {% endfor %}
+ {% endif %}
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% extends "layout.twig" %}
+{% block title %}tags{% endblock %}
+{% block menu %}
+{% include '_menu.twig' %}
+{% endblock %}
+{% block content %}
+{% for tag in tags %}<a href="./?view=tag&id={{ tag.id }}">{{ tag.value }}</a> {% if token != '' %}<a href="?feed&type=tag&user_id={{ user_id }}&tag_id={{ tag.id }}&token={{ token }}" target="_blank"><img src="{{ poche_url }}/themes/{{ theme }}/img/{{ theme }}/rss.png" /></a>{% endif %} {% endfor %}
+{% endblock %}
\ No newline at end of file
<header class="mbm">
<h1>{{ entry.title|raw }}</h1>
</header>
+ <aside class="tags">
+ tags: {% for tag in tags %}<a href="./?view=tag&id={{ tag.id }}">{{ tag.value }}</a> {% endfor %}<a href="./?view=edit-tags&id={{ entry.id|e }}" title="{% trans "edit tags" %}">✎</a>
+ </aside>
<article>
{{ content | raw }}
</article>