PageRenderTime 29ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/tags/tags.php

http://github.com/vito/chyrp
PHP | 733 lines | 664 code | 68 blank | 1 comment | 26 complexity | c6d5a602a6964b5f7ae200a78d328b01 MD5 | raw file
  1. <?php
  2. class Tags extends Modules {
  3. public function __init() {
  4. $this->addAlias("metaWeblog_newPost_preQuery", "metaWeblog_editPost_preQuery");
  5. $this->addAlias("javascript", "tagsJS");
  6. }
  7. static function __install() {
  8. Route::current()->add("tag/(name)/", "tag");
  9. }
  10. static function __uninstall($confirm) {
  11. Route::current()->remove("tag/(name)/");
  12. }
  13. public function admin_head() {
  14. $config = Config::current();
  15. ?>
  16. <script type="text/javascript">
  17. <?php $this->tagsJS(); ?>
  18. </script>
  19. <link rel="stylesheet" href="<?php echo $config->chyrp_url; ?>/modules/tags/admin.css" type="text/css" media="screen" title="no title" charset="utf-8" />
  20. <?php
  21. }
  22. public function post_options($fields, $post = null) {
  23. $tags = self::list_tags(false);
  24. $selector = '<span class="tags_select">'."\n";
  25. foreach (array_reverse($tags) as $tag) {
  26. $selected = ($post and isset($post->tags[$tag["name"]])) ?
  27. ' class="tag_added"' :
  28. "" ;
  29. $selector.= "\t\t\t\t\t\t\t\t".'<a href="javascript:add_tag(\''.addslashes($tag["name"]).'\')"'.$selected.'>'.$tag["name"].'</a>'."\n";
  30. }
  31. $selector.= "\t\t\t\t\t\t\t</span><br /><br />";
  32. if (isset($post->tags))
  33. $tags = array_keys($post->tags);
  34. else
  35. $tags = array();
  36. $fields[] = array("attr" => "tags",
  37. "label" => __("Tags", "tags"),
  38. "note" => __("(comma separated)", "tags"),
  39. "type" => "text",
  40. "value" => implode(", ", $tags),
  41. "extra" => $selector);
  42. return $fields;
  43. }
  44. public function bookmarklet_submit_values(&$values) {
  45. $tags = array();
  46. foreach ($values as $key =>&$value) {
  47. $paragraphs = preg_split("/([\r\n]{2,4})/", $value);
  48. $rejoin = ((strlen($value) - strlen(implode("", $paragraphs)) / count($paragraphs)) == 4) ? "\r\n\r\n" : "\n\n" ;
  49. foreach ($paragraphs as $index => &$paragraph)
  50. # Look for #spaced tags# that get removed only in the last paragraph.
  51. if ($index + 1 == count($paragraphs) and trim(preg_replace("/(\s|^)#([^#]+)(?!\\\\)#/", "\\1", $paragraph)) == "") {
  52. if (preg_match_all("/(\s|^)#([^#]+)(?!\\\\)#/", $paragraph, $double)) { # Look for normal tags.
  53. $tags = array_merge($double[2], $tags);
  54. $paragraph = preg_replace("/(\s|^)#([^#]+)(?!\\\\)#/", "\\1", $paragraph);
  55. }
  56. break;
  57. } elseif (preg_match_all("/(\s|^)#([^ .,]+)(?!#)/", $paragraph, $single)) {
  58. $tags = array_merge($single[2], $tags);
  59. $paragraph = preg_replace("/(\s|^)#([^ .,]+)(?!#)/", "\\1\\2", $paragraph);
  60. }
  61. $value = str_replace("\\#", "#", implode($rejoin, $paragraphs));
  62. }
  63. $_POST['tags'] = implode(", ", $tags);
  64. }
  65. public function add_post($post) {
  66. if (empty($_POST['tags'])) return;
  67. $tags = explode(",", $_POST['tags']); # Split at the comma
  68. $tags = array_map("trim", $tags); # Remove whitespace
  69. $tags = array_map("strip_tags", $tags); # Remove HTML
  70. $tags = array_unique($tags); # Remove duplicates
  71. $tags = array_diff($tags, array("")); # Remove empties
  72. $tags_cleaned = array_map("sanitize", $tags);
  73. $tags = array_combine($tags, $tags_cleaned);
  74. SQL::current()->insert("post_attributes",
  75. array("name" => "tags",
  76. "value" => YAML::dump($tags),
  77. "post_id" => $post->id));
  78. }
  79. public function update_post($post) {
  80. if (empty($_POST['tags']))
  81. SQL::current()->delete("post_attributes",
  82. array("name" => "tags",
  83. "post_id" => $post->id));
  84. $tags = explode(",", $_POST['tags']); # Split at the comma
  85. $tags = array_map('trim', $tags); # Remove whitespace
  86. $tags = array_map('strip_tags', $tags); # Remove HTML
  87. $tags = array_unique($tags); # Remove duplicates
  88. $tags = array_diff($tags, array("")); # Remove empties
  89. $tags_cleaned = array_map("sanitize", $tags);
  90. $tags = array_combine($tags, $tags_cleaned);
  91. SQL::current()->replace("post_attributes",
  92. array("post_id", "name"),
  93. array("name" => "tags",
  94. "value" => YAML::dump($tags),
  95. "post_id" => $post->id));
  96. }
  97. public function parse_urls($urls) {
  98. $urls["|/tag/([^/]+)/|"] = "/?action=tag&name=$1";
  99. return $urls;
  100. }
  101. public function manage_posts_column_header() {
  102. echo "<th>".__("Tags", "tags")."</th>";
  103. }
  104. public function manage_posts_column($post) {
  105. echo "<td>".implode(", ", $post->linked_tags)."</td>";
  106. }
  107. static function manage_nav($navs) {
  108. if (!Post::any_editable())
  109. return $navs;
  110. $navs["manage_tags"] = array("title" => __("Tags", "tags"),
  111. "selected" => array("rename_tag", "delete_tag", "edit_tags"));
  112. return $navs;
  113. }
  114. static function manage_nav_pages($pages) {
  115. array_push($pages, "manage_tags", "rename_tag", "delete_tag", "edit_tags");
  116. return $pages;
  117. }
  118. public function admin_manage_tags($admin) {
  119. if (!Post::any_editable())
  120. show_403(__("Access Denied"), __("You do not have sufficient privileges to manage tags.", "tags"));
  121. $sql = SQL::current();
  122. $tags = array();
  123. $names = array();
  124. foreach($sql->select("post_attributes",
  125. "*",
  126. array("name" => "tags"))->fetchAll() as $tag) {
  127. $post_tags = YAML::load($tag["value"]);
  128. $tags = array_merge($tags, $post_tags);
  129. foreach ($post_tags as $name => $clean)
  130. $names[] = $name;
  131. }
  132. $popularity = array_count_values($names);
  133. $cloud = array();
  134. if (!empty($popularity)) {
  135. $max_qty = max($popularity);
  136. $min_qty = min($popularity);
  137. $spread = $max_qty - $min_qty;
  138. if ($spread == 0)
  139. $spread = 1;
  140. $step = 75 / $spread;
  141. foreach ($popularity as $tag => $count)
  142. $cloud[] = array("size" => (100 + (($count - $min_qty) * $step)),
  143. "popularity" => $count,
  144. "name" => $tag,
  145. "title" => sprintf(_p("%s post tagged with &quot;%s&quot;", "%s posts tagged with &quot;%s&quot;", $count, "tags"), $count, $tag),
  146. "clean" => $tags[$tag],
  147. "url" => url("tag/".$tags[$tag], MainController::current()));
  148. }
  149. fallback($_GET['query'], "");
  150. list($where, $params) = keywords($_GET['query'], "post_attributes.value LIKE :query OR url LIKE :query");
  151. $visitor = Visitor::current();
  152. if (!$visitor->group->can("view_draft", "edit_draft", "edit_post", "delete_draft", "delete_post"))
  153. $where["user_id"] = $visitor->id;
  154. $results = Post::find(array("placeholders" => true,
  155. "where" => $where,
  156. "params" => $params));
  157. $ids = array();
  158. foreach ($results[0] as $result)
  159. $ids[] = $result["id"];
  160. if (!empty($ids))
  161. $posts = new Paginator(Post::find(array("placeholders" => true,
  162. "drafts" => true,
  163. "where" => array("id" => $ids))),
  164. 25);
  165. else
  166. $posts = new Paginator(array());
  167. $admin->display("manage_tags", array("tag_cloud" => $cloud,
  168. "posts" => $posts));
  169. }
  170. public function admin_rename_tag($admin) {
  171. if (!Visitor::current()->group->can("edit_post"))
  172. show_403(__("Access Denied"), __("You do not have sufficient privileges to edit tags.", "tags"));
  173. $sql = SQL::current();
  174. $tags = array();
  175. $names = array();
  176. foreach($sql->select("post_attributes",
  177. "*",
  178. array("name" => "tags",
  179. "value like" => self::yaml_match($_GET['name'])))->fetchAll() as $tag) {
  180. $post_tags = YAML::load($tag["value"]);
  181. $tags = array_merge($tags, $post_tags);
  182. foreach ($post_tags as $name => $clean)
  183. $names[] = $name;
  184. }
  185. $popularity = array_count_values($names);
  186. foreach ($popularity as $tag => $count)
  187. if ($tags[$tag] == $_GET['name']) {
  188. $tag = array("name" => $tag, "clean" => $tags[$tag]);
  189. break;
  190. }
  191. $admin->display("rename_tag", array("tag" => $tag));
  192. }
  193. public function admin_edit_tags($admin) {
  194. if (empty($_GET['id']))
  195. error(__("No ID Specified"), __("Please specify the ID of the post whose tags you would like to edit.", "tags"));
  196. $post = new Post($_GET['id']);
  197. if (!$post->editable())
  198. show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post."));
  199. $admin->display("edit_tags", array("post" => new Post($_GET['id'])));
  200. }
  201. public function admin_update_tags($admin) {
  202. if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
  203. show_403(__("Access Denied"), __("Invalid security key."));
  204. if (!isset($_POST['id']))
  205. error(__("No ID Specified"), __("Please specify the ID of the post whose tags you would like to edit.", "tags"));
  206. $post = new Post($_POST['id']);
  207. if (!$post->editable())
  208. show_403(__("Access Denied"), __("You do not have sufficient privileges to edit this post."));
  209. $this->update_post($post);
  210. Flash::notice(__("Tags updated.", "tags"), "/admin/?action=manage_tags");
  211. }
  212. public function admin_update_tag($admin) {
  213. if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
  214. show_403(__("Access Denied"), __("Invalid security key."));
  215. if (!Visitor::current()->group->can("edit_post"))
  216. show_403(__("Access Denied"), __("You do not have sufficient privileges to edit tags.", "tags"));
  217. $sql = SQL::current();
  218. $tags = array();
  219. $clean = array();
  220. foreach($sql->select("post_attributes",
  221. "*",
  222. array("name" => "tags",
  223. "value like" => "%\n".$_POST['original'].": \"%"))->fetchAll() as $tag) {
  224. $tags = YAML::load($tag["value"]);
  225. unset($tags[$_POST['original']]);
  226. $tags[$_POST['name']] = sanitize($_POST['name']);
  227. $sql->update("post_attributes",
  228. array("name" => "tags",
  229. "post_id" => $tag["post_id"]),
  230. array("value" => YAML::dump($tags)));
  231. }
  232. Flash::notice(__("Tag renamed.", "tags"), "/admin/?action=manage_tags");
  233. }
  234. public function admin_delete_tag($admin) {
  235. $sql = SQL::current();
  236. foreach($sql->select("post_attributes",
  237. "*",
  238. array("name" => "tags",
  239. "value like" => self::yaml_match($_GET['clean'])))->fetchAll() as $tag) {
  240. $tags = YAML::load($tag["value"]);
  241. unset($tags[$_GET['name']]);
  242. if (empty($tags))
  243. $sql->delete("post_attributes", array("name" => "tags", "post_id" => $tag["post_id"]));
  244. else
  245. $sql->update("post_attributes",
  246. array("name" => "tags",
  247. "post_id" => $tag["post_id"]),
  248. array("value" => YAML::dump($tags)));
  249. }
  250. Flash::notice(__("Tag deleted.", "tags"), "/admin/?action=manage_tags");
  251. }
  252. public function admin_bulk_tag($admin) {
  253. if (!isset($_POST['hash']) or $_POST['hash'] != Config::current()->secure_hashkey)
  254. show_403(__("Access Denied"), __("Invalid security key."));
  255. if (empty($_POST['name']) or empty($_POST['post']))
  256. redirect("/admin/?action=manage_tags");
  257. $sql = SQL::current();
  258. foreach (array_map("trim", explode(",", $_POST['name'])) as $tag)
  259. foreach ($_POST['post'] as $post_id) {
  260. $post = new Post($post_id);
  261. if (!$post->editable())
  262. continue;
  263. $tags = $sql->select("post_attributes",
  264. "value",
  265. array("name" => "tags",
  266. "post_id" => $post_id));
  267. if ($tags and $value = $tags->fetchColumn())
  268. $tags = YAML::load($value);
  269. else
  270. $tags = array();
  271. $tags[$tag] = sanitize($tag);
  272. $sql->replace("post_attributes",
  273. array("post_id", "name"),
  274. array("name" => "tags",
  275. "value" => YAML::dump($tags),
  276. "post_id" => $post_id));
  277. }
  278. Flash::notice(__("Posts tagged.", "tags"), "/admin/?action=manage_tags");
  279. }
  280. public function main_tag($main) {
  281. if (!isset($_GET['name']))
  282. return $main->resort(array("pages/tag", "pages/index"),
  283. array("reason" => "no_tag_specified"),
  284. __("No Tag", "tags"));
  285. $sql = SQL::current();
  286. $tags = explode(" ", $_GET['name']);
  287. $likes = array();
  288. foreach ($tags as $name)
  289. $likes[] = self::yaml_match($name);
  290. $attributes = $sql->select("post_attributes",
  291. array("value", "post_id"),
  292. array("name" => "tags",
  293. "value like all" => $likes));
  294. $ids = array();
  295. foreach ($attributes->fetchAll() as $index => $row) {
  296. foreach ($tags as &$tag) {
  297. $search = array_search($tag, YAML::load($row["value"]));
  298. $tag = ($search) ? $search : $tag;
  299. }
  300. $ids[] = $row["post_id"];
  301. }
  302. $tag = list_notate($tags, true);
  303. if (empty($ids))
  304. return $main->resort(array("pages/tag", "pages/index"),
  305. array("reason" => "tag_not_found"),
  306. __("Invalid Tag", "tags"));
  307. $posts = new Paginator(Post::find(array("placeholders" => true,
  308. "where" => array("id" => $ids))),
  309. Config::current()->posts_per_page);
  310. if (empty($posts))
  311. return false;
  312. $main->display(array("pages/tag", "pages/index"),
  313. array("posts" => $posts, "tag" => $tag, "tags" => $tags),
  314. _f("Posts tagged with %s", array($tag), "tags"));
  315. }
  316. public function main_tags($main) {
  317. $sql = SQL::current();
  318. if ($sql->count("post_attributes", array("name" => "tags")) > 0) {
  319. $tags = array();
  320. $names = array();
  321. foreach($sql->select("posts",
  322. "post_attributes.*",
  323. array("post_attributes.name" => "tags", Post::statuses(), Post::feathers()),
  324. null,
  325. array(),
  326. null, null, null,
  327. array(array("table" => "post_attributes",
  328. "where" => "post_id = posts.id")))->fetchAll() as $tag) {
  329. $post_tags = YAML::load($tag["value"]);
  330. $tags = array_merge($tags, $post_tags);
  331. foreach ($post_tags as $name => $clean)
  332. $names[] = $name;
  333. }
  334. $popularity = array_count_values($names);
  335. if (empty($popularity))
  336. return $main->resort("pages/tags", array("tag_cloud" => array()), __("No Tags", "tags"));
  337. $max_qty = max($popularity);
  338. $min_qty = min($popularity);
  339. $spread = $max_qty - $min_qty;
  340. if ($spread == 0)
  341. $spread = 1;
  342. $step = 250 / $spread; # Increase for bigger difference.
  343. $context = array();
  344. foreach ($popularity as $tag => $count)
  345. $context[] = array("size" => (100 + (($count - $min_qty) * $step)),
  346. "popularity" => $count,
  347. "name" => $tag,
  348. "title" => sprintf(_p("%s post tagged with &quot;%s&quot;", "%s posts tagged with &quot;%s&quot;", $count, "tags"), $count, $tag),
  349. "clean" => $tags[$tag],
  350. "url" => url("tag/".$tags[$tag], $main));
  351. $main->display("pages/tags", array("tag_cloud" => $context), __("Tags", "tags"));
  352. }
  353. }
  354. public function import_wordpress_post($item, $post) {
  355. if (!isset($item->category)) return;
  356. $tags = array();
  357. foreach ($item->category as $tag)
  358. if (isset($tag->attributes()->domain) and $tag->attributes()->domain == "tag" and !empty($tag) and isset($tag->attributes()->nicename))
  359. $tags[strip_tags(trim($tag))] = sanitize(strip_tags(trim($tag)));
  360. if (!empty($tags))
  361. SQL::current()->insert("post_attributes",
  362. array("name" => "tags",
  363. "value" => YAML::dump($tags),
  364. "post_id" => $post->id));
  365. }
  366. public function import_movabletype_post($array, $post, $link) {
  367. $get_pointers = mysql_query("SELECT * FROM mt_objecttag WHERE objecttag_object_id = {$array["entry_id"]} ORDER BY objecttag_object_id ASC", $link) or error(__("Database Error"), mysql_error());
  368. if (!mysql_num_rows($get_pointers))
  369. return;
  370. $tags = array();
  371. while ($pointer = mysql_fetch_array($get_pointers)) {
  372. $get_dirty_tag = mysql_query("SELECT tag_name, tag_n8d_id FROM mt_tag WHERE tag_id = {$pointer["objecttag_tag_id"]}", $link) or error(__("Database Error"), mysql_error());
  373. if (!mysql_num_rows($get_dirty_tag)) continue;
  374. $dirty_tag = mysql_fetch_array($get_dirty_tag);
  375. $dirty = $dirty_tag["tag_name"];
  376. $clean_tag = mysql_query("SELECT tag_name FROM mt_tag WHERE tag_id = {$dirty_tag["tag_n8d_id"]}", $link) or error(__("Database Error"), mysql_error());
  377. if (mysql_num_rows($clean_tag))
  378. $clean = mysql_result($clean_tag, 0);
  379. else
  380. $clean = $dirty;
  381. $tags[$dirty] = $clean;
  382. }
  383. if (empty($tags))
  384. return;
  385. SQL::current()->insert("post_attributes", array("name" => "tags", "value" => YAML::dump($tags), "post_id" => $post->id));
  386. }
  387. public function metaWeblog_getPost($struct, $post) {
  388. if (!isset($post->tags))
  389. $struct['mt_tags'] = "";
  390. else
  391. $struct['mt_tags'] = implode(", ", array_keys($post->tags));
  392. return $struct;
  393. }
  394. public function metaWeblog_editPost_preQuery($struct, $post = null) {
  395. if (isset($struct['mt_tags']))
  396. $_POST['tags'] = $struct['mt_tags'];
  397. else if (isset($post->tags))
  398. $_POST['tags'] = $post->unlinked_tags;
  399. else
  400. $_POST['tags'] = '';
  401. }
  402. public function main_context($context) {
  403. $context["tags"] = self::list_tags();
  404. return $context;
  405. }
  406. static function linked_tags($tags) {
  407. if (empty($tags))
  408. return array();
  409. $linked = array();
  410. foreach ($tags as $tag => $clean)
  411. $linked[] = '<a href="'.url("tag/".urlencode($clean), MainController::current()).'" rel="tag">'.$tag.'</a>';
  412. return $linked;
  413. }
  414. public function post($post) {
  415. $post->tags = !empty($post->tags) ? YAML::load($post->tags) : array() ;
  416. $post->linked_tags = self::linked_tags($post->tags);
  417. }
  418. public function sort_tags_name_asc($a, $b) {
  419. return strcmp($a["name"], $b["name"]);
  420. }
  421. public function sort_tags_name_desc($a, $b) {
  422. return strcmp($b["name"], $a["name"]);
  423. }
  424. public function sort_tags_popularity_asc($a, $b) {
  425. return $a["popularity"] > $b["popularity"];
  426. }
  427. public function sort_tags_popularity_desc($a, $b) {
  428. return $a["popularity"] < $b["popularity"];
  429. }
  430. public function list_tags($limit = 10, $order_by = "popularity", $order = "desc") {
  431. $sql = SQL::current();
  432. $attrs = $sql->select("posts",
  433. "post_attributes.value",
  434. array("post_attributes.name" => "tags", Post::statuses(), Post::feathers()),
  435. null,
  436. array(),
  437. null, null, null,
  438. array(array("table" => "post_attributes",
  439. "where" => "post_id = posts.id")));
  440. $tags = array();
  441. $names = array();
  442. while ($attr = $attrs->fetchObject()) {
  443. $post_tags = YAML::load($attr->value);
  444. $tags = array_merge($tags, $post_tags);
  445. foreach ($post_tags as $name => $clean)
  446. $names[] = $name;
  447. }
  448. if (empty($tags))
  449. return array();
  450. $popularity = array_count_values($names);
  451. $list = array();
  452. foreach ($popularity as $name => $number)
  453. $list[$name] = array("name" => $name,
  454. "popularity" => $number,
  455. "percentage" => $number / array_sum($popularity),
  456. "url" => urlencode($tags[$name]),
  457. "clean" => $tags[$name]);
  458. usort($list, array($this, "sort_tags_".$order_by."_".$order));
  459. return ($limit) ? array_slice($list, 0, $limit) : $list ;
  460. }
  461. public function yaml_match($name) {
  462. $dumped = YAML::dump(array($name));
  463. $quotes = preg_match("/- \"".preg_quote($name, "/")."\"/", $dumped);
  464. return ($quotes ? "%: \"".$name."\"\n%" : "%: ".$name."\n%");
  465. }
  466. public function tagsJS() {
  467. $config = Config::current();
  468. ?>//<script>
  469. $(function(){
  470. function scanTags(){
  471. $(".tags_select a").each(function(){
  472. regexp = new RegExp("(, ?|^)"+ $(this).text() +"(, ?|$)", "g")
  473. if ($("#tags").val().match(regexp))
  474. $(this).addClass("tag_added")
  475. else
  476. $(this).removeClass("tag_added")
  477. })
  478. }
  479. scanTags()
  480. $("#tags").live("keyup", scanTags)
  481. $(".tag_cloud > span").live("mouseover", function(){
  482. $(this).find(".controls").css("opacity", 1)
  483. }).live("mouseout", function(){
  484. $(this).find(".controls").css("opacity", 0)
  485. })
  486. $(".tag_cloud span a").draggable({
  487. zIndex: 100,
  488. revert: true
  489. });
  490. $(".post_tags li:not(.toggler)").droppable({
  491. accept: ".tag_cloud span a",
  492. tolerance: "pointer",
  493. activeClass: "active",
  494. hoverClass: "hover",
  495. drop: function(ev, ui) {
  496. var post_id = $(this).attr("id").replace(/post-/, "");
  497. var self = this;
  498. $.ajax({
  499. type: "post",
  500. dataType: "json",
  501. url: "<?php echo $config->chyrp_url; ?>/includes/ajax.php",
  502. data: {
  503. action: "tag_post",
  504. post: post_id,
  505. name: $(ui.draggable).text()
  506. },
  507. beforeSend: function(){
  508. $(self).loader();
  509. },
  510. success: function(json){
  511. $(self).loader(true);
  512. $(document.createElement("a")).attr("href", json.url).addClass("tag").addClass("dropped").text(json.tag).insertBefore($(self).find(".edit_tag"));
  513. }
  514. });
  515. }
  516. });
  517. })
  518. function add_tag(name) {
  519. if ($("#tags").val().match("(, |^)"+ name +"(, |$)")) {
  520. regexp = new RegExp("(, |^)"+ name +"(, |$)", "g")
  521. $("#tags").val($("#tags").val().replace(regexp, function(match, before, after){
  522. if (before == ", " && after == ", ")
  523. return ", "
  524. else
  525. return ""
  526. }))
  527. $(".tags_select a").each(function(){
  528. if ($(this).text() == name)
  529. $(this).removeClass("tag_added")
  530. })
  531. } else {
  532. if ($("#tags").val() == "")
  533. $("#tags").val(name)
  534. else
  535. $("#tags").val($("#tags").val().replace(/(, ?)?$/, ", "+ name))
  536. $(".tags_select a").each(function(){
  537. if ($(this).text() == name)
  538. $(this).addClass("tag_added")
  539. })
  540. }
  541. }
  542. <?php
  543. }
  544. public function ajax_tag_post() {
  545. if (empty($_POST['name']) or empty($_POST['post']))
  546. exit("{}");
  547. $sql = SQL::current();
  548. $post = new Post($_POST['post']);
  549. $tag = $_POST['name'];
  550. if (!$post->editable())
  551. exit("{}");
  552. $tags = $sql->select("post_attributes",
  553. "value",
  554. array("name" => "tags",
  555. "post_id" => $post->id));
  556. if ($tags and $value = $tags->fetchColumn())
  557. $tags = YAML::load($value);
  558. else
  559. $tags = array();
  560. $tags[$tag] = sanitize($tag);
  561. $sql->replace("post_attributes",
  562. array("post_id", "name"),
  563. array("name" => "tags",
  564. "value" => YAML::dump($tags),
  565. "post_id" => $post->id));
  566. exit("{ \"url\": \"".url("tag/".$tags[$tag], MainController::current())."\", tag: \"".$_POST['name']."\" }");
  567. }
  568. function feed_item($post) {
  569. $config = Config::current();
  570. foreach ($post->tags as $tag => $clean)
  571. echo " <category scheme=\"".$config->url."/tag/\" term=\"".$clean."\" label=\"".fix($tag)."\" />\n";
  572. }
  573. }