diff --git a/plugins/Nodeinfo/NodeinfoPlugin.php b/plugins/Nodeinfo/NodeinfoPlugin.php index 5c23ac5e57..07a86e93f7 100644 --- a/plugins/Nodeinfo/NodeinfoPlugin.php +++ b/plugins/Nodeinfo/NodeinfoPlugin.php @@ -27,13 +27,153 @@ class NodeinfoPlugin extends Plugin return true; } + /** + * Make sure necessary tables are filled out. + * + * @return boolean hook true + */ + public function onCheckSchema() + { + // Ensure schema + $schema = Schema::get(); + $schema->ensureTable('usage_stats', Usage_stats::schemaDef()); + + // Ensure default rows + if (Usage_stats::getKV('type', 'users') == null) { + $us = new Usage_stats(); + $us->type = 'users'; + $us->insert(); + } + + if (Usage_stats::getKV('type', 'posts') == null) { + $us = new Usage_stats(); + $us->type = 'posts'; + $us->insert(); + } + + if (Usage_stats::getKV('type', 'comments') == null) { + $us = new Usage_stats(); + $us->type = 'comments'; + $us->insert(); + } + + return true; + } + + /** + * Increment notices/replies counter + * + * @return boolean hook flag + * @author Diogo Cordeiro + */ + public function onStartNoticeDistribute($notice) + { + assert($notice->id > 0); // Ignore if not a valid notice + + $profile = $notice->getProfile(); + + if (!$profile->isLocal()) { + return true; + } + + // Ignore for activity/non-post-verb notices + if (method_exists('ActivityUtils', 'compareVerbs')) { + $is_post_verb = ActivityUtils::compareVerbs( + $notice->verb, + [ActivityVerb::POST] + ); + } else { + $is_post_verb = ($notice->verb == ActivityVerb::POST ? true : false); + } + if ($notice->source == 'activity' || !$is_post_verb) { + return true; + } + + // Is a reply? + if ($notice->reply_to) { + $us = Usage_stats::getKV('type', 'comments'); + $us->count += 1; + $us->update(); + return true; + } + + // Is an Announce? + if ($notice->isRepeat()) { + return true; + } + + $us = Usage_stats::getKV('type', 'posts'); + $us->count += 1; + $us->update(); + + // That was it + return true; + } + + /** + * Decrement notices/replies counter + * + * @return boolean hook flag + * @author Diogo Cordeiro + */ + public function onStartDeleteOwnNotice($user, $notice) + { + $profile = $user->getProfile(); + + // Only count local notices + if (!$profile->isLocal()) { + return true; + } + + if ($notice->reply_to) { + $us = Usage_stats::getKV('type', 'comments'); + $us->count -= 1; + $us->update(); + return true; + } + + $us = Usage_stats::getKV('type', 'posts'); + $us->count -= 1; + $us->update(); + return true; + } + + /** + * Increment users counter + * + * @return boolean hook flag + * @author Diogo Cordeiro + */ + public function onEndRegistrationTry() + { + $us = Usage_stats::getKV('type', 'users'); + $us->count += 1; + $us->update(); + return true; + } + + /** + * Decrement users counter + * + * @return boolean hook flag + * @author Diogo Cordeiro + */ + public function onEndDeleteUser() + { + $us = Usage_stats::getKV('type', 'users'); + $us->count -= 1; + $us->update(); + return true; + } + + public function onPluginVersion(array &$versions) { - $versions[] = array('name' => 'Nodeinfo', + $versions[] = ['name' => 'Nodeinfo', 'version' => self::VERSION, 'author' => 'chimo', 'homepage' => 'https://github.com/chimo/gs-nodeinfo', - 'description' => _m('Plugin that presents basic instance information using the NodeInfo standard.')); + 'description' => _m('Plugin that presents basic instance information using the NodeInfo standard.')]; return true; } } diff --git a/plugins/Nodeinfo/actions/nodeinfo_2_0.php b/plugins/Nodeinfo/actions/nodeinfo_2_0.php index bdd83963e6..411e5c318f 100644 --- a/plugins/Nodeinfo/actions/nodeinfo_2_0.php +++ b/plugins/Nodeinfo/actions/nodeinfo_2_0.php @@ -97,28 +97,24 @@ class Nodeinfo_2_0Action extends ApiAction public function getUserCount() { - $users = new User(); - $userCount = $users->count(); + $users = new Usage_stats(); + $userCount = $users->getUserCount(); return $userCount; } public function getPostCount() { - $notices = new Notice(); - $notices->is_local = Notice::LOCAL_PUBLIC; - $notices->whereAdd('reply_to IS NULL'); - $noticeCount = $notices->count(); + $posts = new Usage_stats(); + $postCount = $posts->getPostCount(); - return $noticeCount; + return $postCount; } public function getCommentCount() { - $notices = new Notice(); - $notices->is_local = Notice::LOCAL_PUBLIC; - $notices->whereAdd('reply_to IS NOT NULL'); - $commentCount = $notices->count(); + $comments = new Usage_stats(); + $commentCount = $comments->getCommentCount(); return $commentCount; } diff --git a/plugins/Nodeinfo/classes/Usage_stats.php b/plugins/Nodeinfo/classes/Usage_stats.php new file mode 100644 index 0000000000..fcfc1c842b --- /dev/null +++ b/plugins/Nodeinfo/classes/Usage_stats.php @@ -0,0 +1,73 @@ +. + */ + +if (!defined('GNUSOCIAL')) { + exit(1); +} + +/** + * Table Definition for Usage_stats + */ +class Usage_stats extends Managed_DataObject +{ + ###START_AUTOCODE + /* the code below is auto generated do not remove the above tag */ + + public $__table = 'usage_stats'; // table name + public $type; // varchar(191) unique_key not 255 because utf8mb4 takes more space + public $count; // int(4) + public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP + + /* the code above is auto generated do not remove the tag below */ + ###END_AUTOCODE + + public static function schemaDef() + { + return [ + 'description' => 'node stats', + 'fields' => [ + 'type' => ['type' => 'varchar', 'length' => 191, 'description' => 'Type of countable entity'], + 'count' => ['type' => 'int', 'size' => 'int', 'default' => 0, 'description' => 'Number of entities of this type'], + + 'modified' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'], + ], + 'primary key' => ['type'], + 'unique keys' => [ + 'usage_stats_key' => ['type'], + ], + 'indexes' => [ + 'user_stats_idx' => ['type'], + ], + ]; + } + + public function getUserCount() + { + return intval(Usage_stats::getKV('type', 'users')->count); + } + + public function getPostCount() + { + return intval(Usage_stats::getKV('type', 'posts')->count); + } + + public function getCommentCount() + { + return intval(Usage_stats::getKV('type', 'comments')->count); + } +} diff --git a/plugins/Nodeinfo/scripts/fix_stats.php b/plugins/Nodeinfo/scripts/fix_stats.php new file mode 100755 index 0000000000..dadb8e447c --- /dev/null +++ b/plugins/Nodeinfo/scripts/fix_stats.php @@ -0,0 +1,117 @@ +#!/usr/bin/env php +. + * + * @category Plugin + * @package GNUsocial + * @copyright 2018 Free Software Foundation http://fsf.org + * @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0 + * @link https://www.gnu.org/software/social/ + */ + +define('INSTALLDIR', realpath(__DIR__ . '/../../..')); + +$longoptions = ['type=']; + +$helptext = <<count = getUserCount(); + $us->update(); +} + +if ($type_to_fix == 'all' || $type_to_fix == 'posts') { + if ($verbose) { + echo "[+] Updating Posts stats...\n"; + } + $us = Usage_stats::getKV('posts'); + $us->count = getPostCount(); + $us->update(); +} + +if ($type_to_fix == 'all' || $type_to_fix == 'comments') { + if ($verbose) { + echo "[+] Updating Comments stats...\n"; + } + $us = Usage_stats::getKV('comments'); + $us->count = getCommentCount(); + $us->update(); +} + +if ($verbose) { + echo "\nDONE.\n"; +} + +/* + * Counting functions + */ + +function getUserCount() +{ + $users = new User(); + $userCount = $users->count(); + + return $userCount; +} + +function getPostCount() +{ + $notices = new Notice(); + $notices->is_local = Notice::LOCAL_PUBLIC; + $notices->whereAdd('reply_to IS NULL'); + $noticeCount = $notices->count(); + + return $noticeCount; +} + +function getCommentCount() +{ + $notices = new Notice(); + $notices->is_local = Notice::LOCAL_PUBLIC; + $notices->whereAdd('reply_to IS NOT NULL'); + $commentCount = $notices->count(); + + return $commentCount; +}