AnonSec Shell
Server IP : 54.36.91.62  /  Your IP : 216.73.217.112
Web Server : Apache
System : Linux webm013.cluster127.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
User : coopiak ( 151928)
PHP Version : 8.3.23
Disable Function : _dyuweyrj4,_dyuweyrj4r,dl
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/coopiak/www/cj79373/components/com_engage/Helper/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ HOME ]     

Current File : /home/coopiak/www/cj79373/components/com_engage/Helper/Meta.php
<?php
/**
 * @package   AkeebaEngage
 * @copyright Copyright (c)2020-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Engage\Site\Helper;

use Akeeba\Engage\Admin\Model\Comments;
use DateInterval;
use Exception;
use FOF40\Container\Container;
use Joomla\CMS\Date\Date;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\User\User;
use Joomla\Registry\Registry;

defined('_JEXEC') or die();

final class Meta
{
	/**
	 * A temporary instance of the component's container
	 *
	 * @var  Container|null
	 */
	private static $container = null;

	/**
	 * Cached results of resource metadata per asset ID
	 *
	 * @var  array
	 */
	private static $cachedMeta = [];

	/**
	 * Number of comments per asset ID
	 *
	 * @var  int[]
	 */
	private static $numCommentsPerAsset = [];

	/**
	 * IDs of comments per asset in the same order they are paginated in the front-end
	 *
	 * @var  array
	 */
	private static $commentIDsPerAsset = [];

	/**
	 * Returns the metadata of an asset.
	 *
	 * This method goes through the onAkeebaEngageGetAssetMeta plugin event, allowing different plugins to return
	 * information about the asset IDs they recognize. The results are cached to avoid expensive roundtrips to the
	 * Joomla plugin event system and the database.
	 *
	 * The returned keys are:
	 *
	 * * `type`: resource type
	 * * `title`: display title
	 * * `category`: display title for the category / parent item of the resource
	 * * `url`: canonical (frontend) or edit (backend) link for the resource; null if not applicable
	 * * `published`: is the asset published?
	 * * `access`: access level for the resource (e.g. article) this asset ID corresponds to; null if it doesn't apply.
	 * * `parent_access`: access level for the resource's parent (e.g. article category); null if it doesn't apply.
	 *
	 * @param   int  $assetId
	 *
	 * @return array
	 */
	public static function getAssetAccessMeta(int $assetId = 0, bool $loadParameters = false): array
	{
		$metaKey    = md5($assetId . '_' . ($loadParameters ? 'with' : 'without') . '_parameters');
		$altMetaKey = md5($assetId . '_with_parameters');

		if (array_key_exists($metaKey, self::$cachedMeta))
		{
			return self::$cachedMeta[$metaKey];
		}

		if (array_key_exists($altMetaKey, self::$cachedMeta))
		{
			return self::$cachedMeta[$altMetaKey];
		}

		self::$cachedMeta[$metaKey] = [
			'type'          => 'unknown',
			'title'         => '',
			'category'      => null,
			'author_name'   => null,
			'author_email'  => null,
			'url'           => null,
			'public_url'    => null,
			'published'     => false,
			'published_on'  => new Date(),
			'access'        => 0,
			'parent_access' => null,
			'parameters'    => new Registry(),
		];

		$container = Container::getInstance('com_engage');
		$platform  = $container->platform;

		$platform->importPlugin('content');
		$pluginResults = $platform->runPlugins('onAkeebaEngageGetAssetMeta', [$assetId, $loadParameters]);

		$pluginResults = array_filter($pluginResults, function ($x) {
			return is_array($x);
		});

		if (empty($pluginResults))
		{
			return self::$cachedMeta[$metaKey];
		}

		$tempRet = array_shift($pluginResults);

		foreach (self::$cachedMeta[$metaKey] as $k => $v)
		{
			if (!array_key_exists($k, $tempRet))
			{
				continue;
			}

			self::$cachedMeta[$metaKey][$k] = $tempRet[$k] ?? $v;
		}

		return self::$cachedMeta[$metaKey];
	}

	/**
	 * Are the comments closed for the specified resource?
	 *
	 * @param   int  $assetId  The asset ID of the resource
	 *
	 * @return  bool
	 */
	public static function areCommentsClosed(int $assetId = 0)
	{
		$meta = self::getAssetAccessMeta($assetId, true);

		/** @var Registry $params */
		$params = $meta['parameters'];

		if ($params->get('comments_enabled', 0) != 1)
		{
			return true;
		}

		$closeAfter = $params->get('comments_close_after', 0);

		if ($closeAfter <= 0)
		{
			return false;
		}

		// Check if the comments are auto-closed.
		/** @var Date $date */
		$date = $meta['published_on'];

		try
		{
			return ($date->add(new DateInterval(sprintf('P%dD', $closeAfter)))->toUnix() <= time());
		}
		catch (Exception $e)
		{
			return false;
		}
	}

	/**
	 * Returns the total number of comments for a specific asset ID
	 *
	 * @param   int  $asset_id  The asset ID to check for the total number of comments
	 *
	 * @return  int
	 */
	public static function getNumCommentsForAsset(int $asset_id): int
	{
		if (isset(self::$numCommentsPerAsset[$asset_id]))
		{
			return self::$numCommentsPerAsset[$asset_id];
		}

		/** @var Comments $model */
		$model                                = self::getContainer()->factory->model('Comments')->tmpInstance();
		self::$numCommentsPerAsset[$asset_id] = $model->asset_id($asset_id)->count() ?? 0;

		return self::$numCommentsPerAsset[$asset_id];
	}

	/**
	 * Returns the comments IDs for an asset, in the same order as they are paginated in the frontend
	 *
	 * @param   int   $asset_id   Asset ID
	 * @param   bool  $asManager  True to take into account unpublished comments
	 *
	 * @return  array
	 */
	public static function getPaginatedCommentIDsForAsset(int $asset_id, bool $asManager = false): array
	{
		if (isset(self::$commentIDsPerAsset[$asset_id]))
		{
			return self::$commentIDsPerAsset[$asset_id];
		}

		/** @var Comments $model */
		$model = self::getContainer()->factory->model('Comments')->tmpInstance();
		$model->asset_id($asset_id);

		if (!$asManager)
		{
			$model->enabled(1);
		}

		self::$commentIDsPerAsset[$asset_id] = array_keys($model->commentIDTreeSliceWithDepth(0, null));

		return self::$commentIDsPerAsset[$asset_id];
	}

	/**
	 * Returns the limitstart required to reach a specific comment in the frontend comments display.
	 *
	 * @param   Comments  $comment          The comment we're looking for
	 * @param   int|null  $commentsPerPage  Number of comments per page. NULL to use global configuration.
	 * @param   bool      $asManager        True to take into account unpublished / spam comments.
	 *
	 * @return  int
	 */
	public static function getLimitStartForComment(Comments $comment, ?int $commentsPerPage = null, bool $asManager = false): int
	{
		// No limit set. Use the configured list limit, must be at least 5.
		if (is_null($commentsPerPage))
		{
			$commentsPerPage = self::getContainer()->platform->getConfig()->get('list_limit', 20);
			$commentsPerPage = max((int) $commentsPerPage, 5);
		}

		$comments = self::getPaginatedCommentIDsForAsset($comment->asset_id, $asManager);
		$index    = array_search($comment->getId(), $comments);

		if ($index === false)
		{
			return 0;
		}

		return intdiv($index, $commentsPerPage) * $commentsPerPage;
	}

	/**
	 * Pseudonymises and removes the content of comments filed by a user.
	 *
	 * All comments filed either directly with their user ID or under their email address are affected.
	 *
	 * The following actions are taken:
	 *
	 * * The comment text is replaced with COM_ENGAGE_COMMENTS_LBL_DELETEDCOMMENT
	 * * The name (for guest comments filed under the user's email) is replaced with COM_ENGAGE_COMMENTS_LBL_DELETEDUSER
	 * * The email (for guest comments filed under the user's email) is replaced with deleted.<USER_ID>@<SITE_HOSTNAME>
	 * * All #__engage_unsubscribe records with that email address are removed
	 *
	 * This is similar to how other sites, e.g. Slashdot, treat user account deletion. If we were to completely delete a
	 * user's comments we would also be deleting the entire conversation below them since we can't have orphan comments.
	 * Deleting the comment's contents is less disruptive. Of course it doesn't do you much good if you were directly
	 * quoted by a different user but that's something you should have thought before saying something regrettable on
	 * the Internet...
	 *
	 * @param   User|null  $user            The user object whose comments will be nuked
	 *
	 * @param   bool       $convertToGuest  True to convert attributed comments to pseudonymized guest comments
	 *
	 * @return  int[]  The comment IDs affected
	 */
	public static function pseudonymiseUserComments(?User $user, bool $convertToGuest = false): array
	{
		if (empty($user))
		{
			return [];
		}

		if ($user->guest)
		{
			return [];
		}

		$cid       = [];
		$container = self::getContainer();
		$db        = $container->db;

		// Nuke comments directly attributed to the user ID
		$q   = $db->getQuery(true)
			->select($db->qn('engage_comment_id'))
			->from($db->qn('#__engage_comments'))
			->where($db->qn('created_by') . ' = ' . $db->q($user->id));
		$cid = $db->setQuery($q)->loadColumn() ?? [];

		$q = $db->getQuery(true)
			->update($db->qn('#__engage_comments'))
			->set($db->qn('body') . ' = ' . $db->q(Text::_('COM_ENGAGE_COMMENTS_LBL_DELETEDCOMMENT')))
			->where($db->qn('created_by') . ' = ' . $db->q($user->id));
		$db->setQuery($q)->execute();

		// Nuke comments attributed to the user's email address
		$uri = Uri::getInstance();
		$q   = $db->getQuery(true)
			->select($db->qn('engage_comment_id'))
			->from($db->qn('#__engage_comments'))
			->where($db->qn('email') . ' = ' . $db->q($user->email));
		$cid = array_merge($cid, $db->setQuery($q)->loadColumn() ?? []);

		$q = $db->getQuery(true)
			->update($db->qn('#__engage_comments'))
			->set([
				$db->qn('body') . ' = ' . $db->q(Text::_('COM_ENGAGE_COMMENTS_LBL_DELETEDCOMMENT')),
				$db->qn('name') . ' = ' . $db->q(Text::sprintf('COM_ENGAGE_COMMENTS_LBL_DELETEDUSER', $user->id)),
				$db->qn('email') . ' = ' . $db->q(sprintf('deleted.%u@%s', $user->id, $uri->getHost())),
			])
			->where($db->qn('email') . ' = ' . $db->q($user->email));
		$db->setQuery($q)->execute();

		/**
		 * If converting the comments to guest comments (when the user record itself is deleted) we need to do some more
		 * post processing for these comments.
		 */
		if ($convertToGuest && !empty($cid))
		{
			$q = $db->getQuery(true)
				->update($db->qn('#__engage_comments'))
				->set([
					$db->qn('body') . ' = ' . $db->q(Text::_('COM_ENGAGE_COMMENTS_LBL_DELETEDCOMMENT')),
					$db->qn('name') . ' = ' . $db->q(Text::sprintf('COM_ENGAGE_COMMENTS_LBL_DELETEDUSER', $user->id)),
					$db->qn('email') . ' = ' . $db->q(sprintf('deleted.%u@%s', $user->id, $uri->getHost())),
				])
				->where($db->qn('engage_comment_id') . ' IN(' . implode(
						',',
						array_filter(array_unique($cid), function ($id) {
							return is_numeric($id) && ($id > 0);
						})
					) . ')');
			$db->setQuery($q)->execute();
		}

		// Remove #__engage_unsubscribe records
		$q = $db->getQuery(true)
			->delete($db->qn('#__engage_unsubscribe'))
			->where($db->qn('email') . ' = ' . $db->q($user->email));
		$db->setQuery($q)->execute();

		return $cid;
	}

	/**
	 * Returns the component's container (temporary instance)
	 *
	 * @return  Container|null
	 */
	private static function getContainer(): Container
	{
		if (is_null(self::$container))
		{
			self::$container = Container::getInstance('com_engage');
		}

		return self::$container;
	}
}

Anon7 - 2022
AnonSec Team