878 lines
28 KiB
PHP
878 lines
28 KiB
PHP
<?php
|
|
class Tags extends Modules {
|
|
# Array: $caches
|
|
# Query caches for methods.
|
|
private $caches = array();
|
|
|
|
public static function __install(): void {
|
|
Route::current()->add("tag/(name)/", "tag");
|
|
}
|
|
|
|
public static function __uninstall($confirm): void {
|
|
Route::current()->remove("tag/(name)/");
|
|
|
|
if ($confirm)
|
|
SQL::current()->delete(
|
|
table:"post_attributes",
|
|
conds:array("name" => "tags")
|
|
);
|
|
}
|
|
|
|
private function tags_serialize($tags) {
|
|
return json_set($tags);
|
|
}
|
|
|
|
private function tags_unserialize($tags) {
|
|
return json_get($tags, true);
|
|
}
|
|
|
|
private function sort_tags_name_asc($a, $b): int {
|
|
return $this->mb_strcasecmp(
|
|
$a["name"],
|
|
$b["name"]
|
|
);
|
|
}
|
|
|
|
private function sort_tags_name_desc($a, $b): int {
|
|
return $this->mb_strcasecmp(
|
|
$b["name"],
|
|
$a["name"]
|
|
);
|
|
}
|
|
|
|
private function sort_tags_popularity_asc($a, $b): int {
|
|
if ($a["popularity"] == $b["popularity"])
|
|
return 0;
|
|
|
|
return ($a["popularity"] < $b["popularity"]) ? -1 : 1 ;
|
|
}
|
|
|
|
private function sort_tags_popularity_desc($a, $b): int {
|
|
if ($a["popularity"] == $b["popularity"])
|
|
return 0;
|
|
|
|
return ($a["popularity"] > $b["popularity"]) ? -1 : 1 ;
|
|
}
|
|
|
|
private function mb_strcasecmp($str1, $str2, $encoding = "UTF-8"): int {
|
|
$str1 = preg_replace("/[[:punct:]]+/", "", $str1);
|
|
$str2 = preg_replace("/[[:punct:]]+/", "", $str2);
|
|
|
|
return substr_compare(
|
|
mb_strtoupper($str1, $encoding),
|
|
mb_strtoupper($str2, $encoding),
|
|
0
|
|
);
|
|
}
|
|
|
|
private function tags_name_match($name): string {
|
|
# Serialized notation of key for SQL queries.
|
|
return "%\"".$this->tags_encoded($name)."\":%";
|
|
}
|
|
|
|
private function tags_clean_match($clean): string {
|
|
# Serialized notation of value for SQL queries.
|
|
return "%:\"".$this->tags_encoded($clean)."\"%";
|
|
}
|
|
|
|
private function tags_encoded($text): string {
|
|
# Recreate JSON encoding for SQL queries.
|
|
$json = trim(json_set((string) $text), "\"");
|
|
# See: QueryBuilder::build_conditions().
|
|
return str_replace("|", "||", $json);
|
|
}
|
|
|
|
private function prepare_tags($tags): array {
|
|
# Split at the comma.
|
|
$names = explode(",", $tags);
|
|
|
|
# Remove HTML.
|
|
$names = array_map("strip_tags", $names);
|
|
|
|
# Remove whitespace.
|
|
$names = array_map("trim", $names);
|
|
|
|
# Prevent numbers from being type-juggled to numeric keys.
|
|
foreach ($names as &$name) {
|
|
$name = is_numeric($name) ? "'".$name."'" : $name ;
|
|
}
|
|
|
|
# Remove duplicates.
|
|
$names = array_unique($names);
|
|
|
|
# Remove empties.
|
|
$names = array_diff($names, array(""));
|
|
|
|
# Build an array containing a sanitized slug for each tag.
|
|
$clean = array_map(function($value) {
|
|
return sanitize($value, true, SLUG_STRICT, 0);
|
|
}, $names);
|
|
|
|
# Build an associative array with tags as the keys and slugs as the values.
|
|
$assoc = array_combine($names, $clean);
|
|
|
|
# Replace any slugs that have been sanitized into nothingness with a hash.
|
|
foreach ($assoc as $name => &$slug) {
|
|
if (!preg_match("/[^\-0-9]+/", $slug))
|
|
$slug = md5($name);
|
|
}
|
|
|
|
return $assoc;
|
|
}
|
|
|
|
public function before_add_post_attributes($attributes): array {
|
|
if (!isset($_POST['tags']))
|
|
return $attributes;
|
|
|
|
$tags = $this->prepare_tags($_POST['tags']);
|
|
$attributes["tags"] = $this->tags_serialize($tags);
|
|
return $attributes;
|
|
}
|
|
|
|
public function before_update_post_attributes($attributes): array {
|
|
if (!isset($_POST['tags']))
|
|
return $attributes;
|
|
|
|
$tags = $this->prepare_tags($_POST['tags']);
|
|
$attributes["tags"] = $this->tags_serialize($tags);
|
|
return $attributes;
|
|
}
|
|
|
|
public function post_options($fields, $post = null): array {
|
|
$cloud = $this->tag_cloud(false, "name_asc");
|
|
$names = isset($post->tags) ?
|
|
array_keys($post->tags) :
|
|
array();
|
|
|
|
$selector = "\n".'<span class="options_extra tags_select">';
|
|
|
|
foreach ($cloud as $tag) {
|
|
$selected = (in_array($tag["name"], $names)) ?
|
|
" tag_added" :
|
|
"" ;
|
|
|
|
$selector.= '<a class="tag'.
|
|
$selected.
|
|
'" href="#" role="button">'.
|
|
$tag["name"].
|
|
'</a> ';
|
|
}
|
|
|
|
$selector.= "</span>"."\n";
|
|
|
|
$fields[] = array(
|
|
"attr" => "tags",
|
|
"label" => __("Tags", "tags"),
|
|
"help" => "tagging_posts",
|
|
"note" => __("(comma separated)", "tags"),
|
|
"type" => "text",
|
|
"value" => implode(", ", $names),
|
|
"extra" => $selector
|
|
);
|
|
|
|
return $fields;
|
|
}
|
|
|
|
public function post($post): void {
|
|
$post->tags = empty($post->tags) ?
|
|
array() :
|
|
$this->tags_unserialize($post->tags) ;
|
|
|
|
uksort($post->tags, function($a, $b) {
|
|
return $this->mb_strcasecmp($a, $b);
|
|
});
|
|
}
|
|
|
|
public function post_tags_link_attr($attr, $post): array {
|
|
$urls = array();
|
|
|
|
if ($post->no_results)
|
|
return $urls;
|
|
|
|
foreach ($post->tags as $name => $clean) {
|
|
$tag = $this->tag_find_by_name($name);
|
|
|
|
if (!empty($tag)) {
|
|
$urls[] = '<a class="tag" href="'.
|
|
$tag["url"].
|
|
'" rel="tag">'.
|
|
$tag["name"].
|
|
'</a>';
|
|
}
|
|
}
|
|
|
|
return $urls;
|
|
}
|
|
|
|
public function twig_function_tag_cloud(
|
|
$limit = false,
|
|
$sort = "name_asc",
|
|
$scale = 300
|
|
): array {
|
|
return $this->tag_cloud($limit, $sort, $scale);
|
|
}
|
|
|
|
public function parse_urls($urls): array {
|
|
$urls['|/tag/([^/]+)/|'] = '/?action=tag&name=$1';
|
|
return $urls;
|
|
}
|
|
|
|
public function manage_nav($navs): array {
|
|
if (Post::any_editable())
|
|
$navs["manage_tags"] = array(
|
|
"title" => __("Tags", "tags"),
|
|
"selected" => array(
|
|
"rename_tag",
|
|
"delete_tag",
|
|
"edit_tags",
|
|
"posts_tagged"
|
|
)
|
|
);
|
|
|
|
return $navs;
|
|
}
|
|
|
|
public function manage_posts_column_header(): string {
|
|
return '<th class="post_tags list">'.
|
|
__("Tags", "tags").
|
|
'</th>';
|
|
}
|
|
|
|
public function manage_posts_column($post): string {
|
|
$tags = array();
|
|
|
|
foreach ($post->tags as $name => $clean)
|
|
$tags[] = '<a class="tag" href="'.
|
|
url("posts_tagged/clean/".urlencode($clean)).
|
|
'">'.
|
|
$name.
|
|
'</a>';
|
|
|
|
return '<td class="post_tags list">'.
|
|
implode(" ", $tags).
|
|
'</td>';
|
|
}
|
|
|
|
public function admin_manage_tags($admin): void {
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to manage tags.", "tags")
|
|
);
|
|
|
|
# Redirect searches to a clean URL or dirty GET depending on configuration.
|
|
if (isset($_POST['search']))
|
|
redirect(
|
|
"manage_tags/search/".
|
|
str_ireplace(
|
|
array("%2F", "%5C"),
|
|
"%5F",
|
|
urlencode($_POST['search'])
|
|
).
|
|
"/"
|
|
);
|
|
|
|
if (isset($_POST['sort']))
|
|
$_SESSION['tags_sort'] = $_POST['sort'];
|
|
|
|
$search = isset($_GET['search']) ? $_GET['search'] : "" ;
|
|
$sort = fallback($_SESSION['tags_sort'], "popularity_desc");
|
|
|
|
$columns = array(
|
|
"name_asc" => __("Name", "tags"),
|
|
"popularity_desc" => __("Posts Tagged", "tags")
|
|
);
|
|
|
|
$tag_cloud = $this->tag_cloud(sort:$sort);
|
|
|
|
if ($search != "") {
|
|
$tags = $tag_cloud;
|
|
$tag_cloud = array();
|
|
$encoded = $this->tags_encoded($search);
|
|
|
|
foreach ($tags as $tag) {
|
|
if (
|
|
substr_count($tag["name"], $encoded) or
|
|
substr_count($tag["clean"], $encoded)
|
|
)
|
|
$tag_cloud[] = $tag;
|
|
}
|
|
}
|
|
|
|
$admin->display(
|
|
"pages".DIR."manage_tags",
|
|
array(
|
|
"tag_cloud" => $tag_cloud,
|
|
"tags_sort" => $sort,
|
|
"tags_columns" => $columns
|
|
)
|
|
);
|
|
}
|
|
|
|
public function admin_posts_tagged($admin): void {
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to manage tags.", "tags")
|
|
);
|
|
|
|
# Redirect searches to a clean URL or dirty GET depending on configuration.
|
|
if (isset($_POST['query']))
|
|
redirect(
|
|
"posts_tagged/query/".
|
|
str_ireplace(
|
|
array("%2F", "%5C"),
|
|
"%5F",
|
|
urlencode($_POST['query'])
|
|
).
|
|
"/"
|
|
);
|
|
|
|
fallback($_GET['query'], "");
|
|
list($where, $params, $order) = keywords(
|
|
$_GET['query'],
|
|
"post_attributes.value LIKE :query OR url LIKE :query",
|
|
"posts"
|
|
);
|
|
|
|
if (isset($_GET['clean']) and $_GET['clean'] != "") {
|
|
$tag = $this->tag_find_by_clean($_GET['clean']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Tag not found.", "tags")
|
|
);
|
|
|
|
$where["post_attributes.name"] = "tags";
|
|
$where["posts.id"] = $tag["post_ids"];
|
|
} else {
|
|
$tag = false;
|
|
}
|
|
|
|
$visitor = Visitor::current();
|
|
|
|
if (!$visitor->group->can("edit_draft", "edit_post", "delete_draft", "delete_post"))
|
|
$where["user_id"] = $visitor->id;
|
|
|
|
$results = Post::find(
|
|
array(
|
|
"placeholders" => true,
|
|
"drafts" => true,
|
|
"where" => $where,
|
|
"params" => $params
|
|
)
|
|
);
|
|
|
|
$ids = array();
|
|
|
|
foreach ($results[0] as $result)
|
|
$ids[] = $result["id"];
|
|
|
|
if (!empty($ids)) {
|
|
$posts = new Paginator(
|
|
Post::find(
|
|
array(
|
|
"placeholders" => true,
|
|
"drafts" => true,
|
|
"where" => array("id" => $ids),
|
|
"order" => $order
|
|
)
|
|
),
|
|
$admin->post_limit
|
|
);
|
|
} else {
|
|
$posts = new Paginator(array());
|
|
}
|
|
|
|
$admin->display(
|
|
"pages".DIR."posts_tagged",
|
|
array("posts" => $posts, "tag" => $tag)
|
|
);
|
|
}
|
|
|
|
public function admin_edit_tags($admin): void {
|
|
if (empty($_GET['id']) or !is_numeric($_GET['id']))
|
|
error(
|
|
__("No ID Specified"),
|
|
__("An ID is required to edit tags.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
$post = new Post(
|
|
$_GET['id'],
|
|
array("drafts" => true)
|
|
);
|
|
|
|
if ($post->no_results)
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Post not found.")
|
|
);
|
|
|
|
if (!$post->editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to edit this post.")
|
|
);
|
|
|
|
$admin->display(
|
|
"pages".DIR."edit_tags",
|
|
array("post" => $post)
|
|
);
|
|
}
|
|
|
|
public function admin_update_tags($admin)/*: never */{
|
|
if (!isset($_POST['hash']) or !Session::check_token($_POST['hash']))
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("Invalid authentication token.")
|
|
);
|
|
|
|
if (empty($_POST['id']) or !is_numeric($_POST['id']))
|
|
error(
|
|
__("No ID Specified"),
|
|
__("An ID is required to update tags.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
$post = new Post(
|
|
$_POST['id'],
|
|
array("drafts" => true)
|
|
);
|
|
|
|
if ($post->no_results)
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Post not found.")
|
|
);
|
|
|
|
if (!$post->editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to edit this post.")
|
|
);
|
|
|
|
$post->update();
|
|
|
|
Flash::notice(
|
|
__("Tags updated.", "tags"),
|
|
"posts_tagged"
|
|
);
|
|
}
|
|
|
|
public function admin_rename_tag($admin): void {
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to rename tags.", "tags")
|
|
);
|
|
|
|
if (empty($_GET['clean']))
|
|
error(
|
|
__("No Tag Specified", "tags"),
|
|
__("Please specify the tag you want to rename.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
$tag = $this->tag_find_by_clean($_GET['clean']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Tag not found.", "tags")
|
|
);
|
|
|
|
$admin->display(
|
|
"pages".DIR."rename_tag",
|
|
array("tag" => $tag)
|
|
);
|
|
}
|
|
|
|
public function admin_update_tag($admin)/*: never */{
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to rename tags.", "tags")
|
|
);
|
|
|
|
if (!isset($_POST['hash']) or !Session::check_token($_POST['hash']))
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("Invalid authentication token.")
|
|
);
|
|
|
|
if (empty($_POST['original']))
|
|
error(
|
|
__("No Tag Specified", "tags"),
|
|
__("Please specify the tag you want to rename.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
if (!isset($_POST['name']) or $_POST['name'] == "")
|
|
error(
|
|
__("Error"),
|
|
__("Name cannot be blank.", "tags"),
|
|
code:422
|
|
);
|
|
|
|
$tag = $this->tag_find_by_name($_POST['original']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Tag not found.", "tags")
|
|
);
|
|
|
|
foreach ($tag["post_ids"] as $post_id) {
|
|
$post = new Post(
|
|
$post_id,
|
|
array("drafts" => true)
|
|
);
|
|
|
|
if (!$post->editable())
|
|
continue;
|
|
|
|
unset($post->tags[$_POST['original']]);
|
|
$post_tags = implode(", ", array_keys($post->tags));
|
|
$_POST['tags'] = $post_tags.", ".$_POST['name'];
|
|
|
|
$post->update();
|
|
}
|
|
|
|
Flash::notice(
|
|
__("Tag renamed.", "tags"),
|
|
"manage_tags"
|
|
);
|
|
}
|
|
|
|
public function admin_delete_tag($admin): void {
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to delete tags.", "tags")
|
|
);
|
|
|
|
if (empty($_GET['clean']))
|
|
error(
|
|
__("No Tag Specified", "tags"),
|
|
__("Please specify the tag you want to delete.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
$tag = $this->tag_find_by_clean($_GET['clean']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Tag not found.", "tags")
|
|
);
|
|
|
|
$admin->display(
|
|
"pages".DIR."delete_tag",
|
|
array("tag" => $tag)
|
|
);
|
|
}
|
|
|
|
public function admin_destroy_tag()/*: never */{
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to delete tags.", "tags")
|
|
);
|
|
|
|
if (!isset($_POST['hash']) or !Session::check_token($_POST['hash']))
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("Invalid authentication token.")
|
|
);
|
|
|
|
if (empty($_POST['name']))
|
|
error(
|
|
__("No Tag Specified", "tags"),
|
|
__("Please specify the tag you want to delete.", "tags"),
|
|
code:400
|
|
);
|
|
|
|
if (!isset($_POST['destroy']) or $_POST['destroy'] != "indubitably")
|
|
redirect("manage_tags");
|
|
|
|
$tag = $this->tag_find_by_name($_POST['name']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("Tag not found.", "tags")
|
|
);
|
|
|
|
foreach ($tag["post_ids"] as $post_id) {
|
|
$post = new Post(
|
|
$post_id,
|
|
array("drafts" => true)
|
|
);
|
|
|
|
if (!$post->editable())
|
|
continue;
|
|
|
|
unset($post->tags[$_POST['name']]);
|
|
|
|
$_POST['tags'] = implode(", ", array_keys($post->tags));
|
|
$post->update();
|
|
}
|
|
|
|
Flash::notice(
|
|
__("Tag deleted.", "tags"),
|
|
"manage_tags"
|
|
);
|
|
}
|
|
|
|
public function admin_bulk_tag($admin)/*: never */{
|
|
if (!Post::any_editable())
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("You do not have sufficient privileges to add tags.", "tags")
|
|
);
|
|
|
|
if (!isset($_POST['hash']) or !Session::check_token($_POST['hash']))
|
|
show_403(
|
|
__("Access Denied"),
|
|
__("Invalid authentication token.")
|
|
);
|
|
|
|
if (empty($_POST['post']))
|
|
Flash::warning(
|
|
__("No posts selected.", "tags"),
|
|
"posts_tagged"
|
|
);
|
|
|
|
if (!isset($_POST['name']) or $_POST['name'] == "")
|
|
Flash::warning(
|
|
__("No tags specified.", "tags"),
|
|
"posts_tagged"
|
|
);
|
|
|
|
foreach ($_POST['post'] as $post_id) {
|
|
$post = new Post(
|
|
$post_id,
|
|
array("drafts" => true)
|
|
);
|
|
|
|
if (!$post->editable())
|
|
continue;
|
|
|
|
$post_tags = implode(", ", array_keys($post->tags));
|
|
$_POST['tags'] = $post_tags.", ".$_POST['name'];
|
|
$post->update();
|
|
}
|
|
|
|
Flash::notice(
|
|
__("Posts tagged.", "tags"),
|
|
"posts_tagged"
|
|
);
|
|
}
|
|
|
|
public function main_tag($main): void {
|
|
if (!isset($_GET['name']))
|
|
Flash::warning(
|
|
__("You did not specify a tag.", "tags"),
|
|
"/"
|
|
);
|
|
|
|
$tag = $this->tag_find_by_clean($_GET['name']);
|
|
|
|
if (empty($tag))
|
|
show_404(
|
|
__("Not Found"),
|
|
__("The tag you specified was not found.", "tags")
|
|
);
|
|
|
|
$posts = new Paginator(
|
|
Post::find(
|
|
array(
|
|
"placeholders" => true,
|
|
"where" => array("id" => $tag["post_ids"])
|
|
)
|
|
),
|
|
$main->post_limit
|
|
);
|
|
|
|
if (!$posts->total)
|
|
show_404(
|
|
__("Not Found"),
|
|
__("There are no posts with the tag you specified.", "tags")
|
|
);
|
|
|
|
$main->display(
|
|
array("pages".DIR."tag", "pages".DIR."index"),
|
|
array("posts" => $posts, "tag" => $tag),
|
|
_f("Posts tagged with “%s”", array($tag["name"]), "tags")
|
|
);
|
|
}
|
|
|
|
public function main_tags($main): void {
|
|
$main->display(
|
|
"pages".DIR."tags",
|
|
array("tag_cloud" => $this->tag_cloud(false, "name_asc")),
|
|
__("Tags", "tags")
|
|
);
|
|
}
|
|
|
|
public function related_posts($ids, $post, $limit): array {
|
|
if (empty($post->tags))
|
|
return $ids;
|
|
|
|
foreach ($post->tags as $name => $clean) {
|
|
$tag = $this->tag_find_by_name($name);
|
|
|
|
if (!empty($tag)) {
|
|
$ids = array_merge(
|
|
$ids,
|
|
array_diff(
|
|
$tag["post_ids"],
|
|
array($post->id)
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
return $ids;
|
|
}
|
|
|
|
public function tag_cloud(
|
|
$limit = false,
|
|
$sort = "popularity_desc",
|
|
$scale = 300
|
|
): array {
|
|
$sql = SQL::current();
|
|
$visitor = Visitor::current();
|
|
|
|
switch ($sort) {
|
|
case 'name_asc':
|
|
$method = array($this, "sort_tags_name_asc");
|
|
break;
|
|
case 'name_desc':
|
|
$method = array($this, "sort_tags_name_desc");
|
|
break;
|
|
case 'popularity_asc':
|
|
$method = array($this, "sort_tags_popularity_asc");
|
|
break;
|
|
default:
|
|
$method = array($this, "sort_tags_popularity_desc");
|
|
}
|
|
|
|
if (!isset($this->caches["tag_cloud"])) {
|
|
$results = $sql->select(
|
|
tables:"posts",
|
|
fields:"post_attributes.*",
|
|
conds:array(
|
|
"post_attributes.name" => "tags",
|
|
(
|
|
$visitor->group->can("view_draft") ?
|
|
Post::statuses(array(Post::STATUS_DRAFT)) :
|
|
Post::statuses()
|
|
),
|
|
Post::feathers()
|
|
),
|
|
left_join:array(
|
|
array(
|
|
"table" => "post_attributes",
|
|
"where" => "post_id = posts.id"
|
|
)
|
|
)
|
|
)->fetchAll();
|
|
|
|
$found = array();
|
|
$names = array();
|
|
$ids = array();
|
|
$cloud = array();
|
|
|
|
foreach ($results as $result) {
|
|
$these = $this->tags_unserialize($result["value"]);
|
|
$found = array_merge($found, $these);
|
|
|
|
foreach ($these as $name => $clean) {
|
|
$names[] = $name;
|
|
$ids[$name][] = $result["post_id"];
|
|
}
|
|
}
|
|
|
|
if (!empty($found)) {
|
|
$popularity = array_count_values($names);
|
|
$min = min($popularity);
|
|
$max = max($popularity);
|
|
|
|
$step = (int) $scale / (
|
|
($min === $max) ? 1 : ($max - $min)
|
|
);
|
|
|
|
foreach ($popularity as $name => $count) {
|
|
$size = floor($step * ($count - $min));
|
|
$title = $this->tag_cloud_title($name, $count);
|
|
|
|
$url = url(
|
|
"tag/".urlencode($found[$name]),
|
|
MainController::current()
|
|
);
|
|
|
|
$cloud[] = array(
|
|
"size" => $size,
|
|
"popularity" => $count,
|
|
"name" => $name,
|
|
"title" => $title,
|
|
"clean" => $found[$name],
|
|
"url" => $url,
|
|
"post_ids" => $ids[$name]
|
|
);
|
|
}
|
|
}
|
|
|
|
$this->caches["tag_cloud"] = $cloud;
|
|
}
|
|
|
|
$array = $this->caches["tag_cloud"];
|
|
usort($array, $method);
|
|
return ($limit) ?
|
|
array_slice($array, 0, $limit) :
|
|
$array ;
|
|
}
|
|
|
|
private function tag_cloud_title($name, $count) {
|
|
$p = _p("%d post tagged with “%s”", "%d posts tagged with “%s”", $count, "tags");
|
|
$title = sprintf($p, $count, fix($name, true));
|
|
return $title;
|
|
}
|
|
|
|
public function tag_find_by_clean($clean): array|false {
|
|
$cloud = $this->tag_cloud();
|
|
|
|
foreach ($cloud as $tag) {
|
|
if ($tag["clean"] === $clean)
|
|
return $tag;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function tag_find_by_name($name): array|false {
|
|
$cloud = $this->tag_cloud();
|
|
|
|
foreach ($cloud as $tag) {
|
|
if ($tag["name"] === $name)
|
|
return $tag;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function feed_item($post, $feed): void {
|
|
$scheme = url("tags", MainController::current());
|
|
|
|
foreach ($post->tags as $tag => $clean)
|
|
$feed->category($clean, $scheme, $tag);
|
|
}
|
|
|
|
public function admin_javascript(): void {
|
|
include MODULES_DIR.DIR."tags".DIR."javascript.php";
|
|
}
|
|
}
|