Your IP : 216.73.216.224


Current Path : /var/www/html/plugins/system/schedulecontent/src/Extension/
Upload File :
Current File : /var/www/html/plugins/system/schedulecontent/src/Extension/ScheduleContent.php

<?php
/**
 * @package        Joomla
 * @subpackage     Membership Pro
 * @author         Tuan Pham Ngoc
 * @copyright      Copyright (C) 2012 - 2026 Ossolution Team
 * @license        GNU/GPL, see LICENSE.php
 */

namespace JoomDonation\MembershipPro\Plugin\System\ScheduleContent\Extension;

use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\Factory;
use Joomla\CMS\Form\Form;
use Joomla\CMS\Language\Associations;
use Joomla\CMS\Language\Multilanguage;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Plugin\CMSPlugin;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Uri\Uri;
use Joomla\Database\DatabaseAwareTrait;
use Joomla\Event\DispatcherInterface;
use Joomla\Event\Event;
use Joomla\Event\SubscriberInterface;
use MPFEventResult;

defined('_JEXEC') or die;

class ScheduleContent extends CMSPlugin implements SubscriberInterface
{
	use DatabaseAwareTrait;
	use MPFEventResult;

	public static function getSubscribedEvents(): array
	{
		return [
			'onAfterRoute'                => 'onAfterRoute',
			'onEditSubscriptionPlan'      => 'onEditSubscriptionPlan',
			'onAfterSaveSubscriptionPlan' => 'onAfterSaveSubscriptionPlan',
			'onContentPrepare'            => 'onContentPrepare',
			'onProfileDisplay'            => 'onProfileDisplay',
		];
	}

	/**
	 * Constructor.
	 *
	 * @param   DispatcherInterface  $dispatcher  The dispatcher
	 * @param   array                $config      An optional associative array of configuration settings
	 */
	public function __construct(DispatcherInterface $dispatcher, array $config)
	{
		parent::__construct($dispatcher, $config);
	}

	/**
	 * Register listeners
	 *
	 * @return void
	 */
	public function registerListeners()
	{
		if (!ComponentHelper::isEnabled('com_osmembership'))
		{
			return;
		}

		parent::registerListeners();
	}

	/**
	 * Render setting form
	 *
	 * @param   Event  $event
	 *
	 * @return void
	 */
	public function onEditSubscriptionPlan(Event $event): void
	{
		/* @var \OSMembershipTablePlan $row */
		[$row] = array_values($event->getArguments());

		if (!$this->isExecutable())
		{
			return;
		}

		ob_start();
		$this->loadLanguage();
		$this->drawSettingForm($row);
		$form = ob_get_contents();
		ob_end_clean();

		$result = [
			'title' => Text::_('OSM_SCHEULE_CONTENT_MANAGER'),
			'form'  => $form,
		];

		$this->addResult($event, $result);
	}

	/**
	 * Store setting into database, in this case, use params field of plans table
	 *
	 * @param   Event  $event
	 *
	 * @return void
	 */
	public function onAfterSaveSubscriptionPlan(Event $event): void
	{
		/**
		 * @var string                  $context
		 * @var \OSMembershipTablePlan  $row
		 * @var array                   $data
		 * @var                         $isNew
		 */
		[$context, $row, $data, $isNew] = array_values($event->getArguments());

		if (!$this->isExecutable())
		{
			return;
		}

		$scheduleContents   = $data['schedulecontent'] ?? [];
		$scheduleContentIds = [];
		$ordering           = 1;

		$db = $this->getDatabase();

		foreach ($scheduleContents as $scheduleContent)
		{
			if (empty($scheduleContent['article_id']))
			{
				continue;
			}

			$rowScheduleContent = new \OSMembershipTableSchedulecontent($db);

			$rowScheduleContent->bind($scheduleContent);

			// Prevent item being moved to new plan on save as copy

			if ($isNew)
			{
				$rowScheduleContent->id = 0;
			}

			$rowScheduleContent->plan_id  = $row->id;
			$rowScheduleContent->ordering = $ordering++;
			$rowScheduleContent->store();
			$scheduleContentIds[] = $rowScheduleContent->id;
		}

		if (!$isNew)
		{
			$query = $db->getQuery(true)
				->delete('#__osmembership_schedulecontent')
				->where('plan_id = ' . $row->id);

			if (count($scheduleContentIds))
			{
				$query->whereNotIn('id', $scheduleContentIds);
			}

			$db->setQuery($query)
				->execute();
		}
	}

	/**
	 * Render setting form
	 *
	 * @param   Event  $event
	 *
	 * @return void
	 */
	public function onProfileDisplay(Event $event): void
	{
		/* @var \OSMembershipTableSubscriber $row */
		[$row] = array_values($event->getArguments());

		ob_start();
		$this->loadLanguage();
		$this->drawScheduleContent($row);
		$form = ob_get_contents();
		ob_end_clean();

		$result = [
			'title' => Text::_('OSM_MY_SCHEDULE_CONTENT'),
			'form'  => $form,
		];

		$this->addResult($event, $result);
	}

	/**
	 * Set access-view for schedule article
	 *
	 * @param   Event  $event
	 *
	 * @return void
	 */
	public function onContentPrepare(Event $event): void
	{
		[$context, $article, $params, $page] = array_values($event->getArguments());

		if ($context != 'com_content.article')
		{
			return;
		}

		// Narrow down access
		if ($params->get('access-view'))
		{
			$params->set('access-view', $this->canAccess($article->id));
		}
	}

	/**
	 * Method to check if current user can access to schedule article
	 *
	 * @param   int  $articleId
	 *
	 * @return  bool
	 */
	private function canAccess($articleId)
	{
		$db    = $this->getDatabase();
		$query = $db->getQuery(true)
			->select('*')
			->from('#__osmembership_schedulecontent')
			->where('article_id = ' . $articleId);
		$db->setQuery($query);
		$rows = $db->loadObjectList();

		if (empty($rows))
		{
			return true;
		}

		$releaseArticleOlderThanXDays = (int) $this->params->get('release_article_older_than_x_days', 0);

		if ($releaseArticleOlderThanXDays > 0)
		{
			$query->clear()
				->select('*')
				->from('#__content')
				->where('id = ' . $articleId);
			$db->setQuery($query);
			$rowArticle = $db->loadObject();

			if ($rowArticle->publish_up && $rowArticle->publish_up != $db->getNullDate())
			{
				$publishedDate = $rowArticle->publish_up;
			}
			else
			{
				$publishedDate = $rowArticle->created;
			}

			$today         = Factory::getDate();
			$publishedDate = Factory::getDate($publishedDate);
			$numberDays    = $publishedDate->diff($today)->days;

			// This article is older than configured number of days, it can be accessed for free
			if ($today >= $publishedDate && $numberDays >= $releaseArticleOlderThanXDays)
			{
				return true;
			}
		}

		$subscriptions = \OSMembershipHelper::callOverridableHelperMethod('Subscription', 'getUserSubscriptionsInfo');

		foreach ($rows as $row)
		{
			if (isset($subscriptions[$row->plan_id]))
			{
				$subscription = $subscriptions[$row->plan_id];

				if ($subscription->active_in_number_days >= $row->number_days)
				{
					return true;
				}
			}
		}

		return false;
	}

	/**
	 * Protect access to articles
	 *
	 * @return void
	 * @throws \Exception
	 */
	public function onAfterRoute(Event $event): void
	{
		$app = $this->getApplication();

		if (!$app->isClient('site'))
		{
			return;
		}

		$user = $app->getIdentity();

		if ($user->authorise('core.admin'))
		{
			return;
		}

		$option = $app->getInput()->getCmd('option');
		$view   = $app->getInput()->getCmd('view');

		if ($option != 'com_content' || $view != 'article')
		{
			return;
		}

		$articleId = $app->getInput()->getInt('id');

		if (!$this->canAccess($articleId))
		{
			if (!$user->id)
			{
				// Redirect user to login page
				$app->redirect(
					Route::_(
						'index.php?option=com_users&view=login&return=' . base64_encode(Uri::getInstance()->toString())
					)
				);
			}
			else
			{
				\OSMembershipHelper::loadLanguage();

				if ($redirectMenuItem = $this->params->get('redirect_menu_item'))
				{
					if (Multilanguage::isEnabled())
					{
						$associations = Associations::getAssociations(
							'com_menus',
							'#__menu',
							'com_menus.item',
							$redirectMenuItem,
							'id',
							'',
							''
						);
						$langCode     = $app->getLanguage()->getTag();

						if (isset($associations[$langCode]))
						{
							$redirectMenuItem = $associations[$langCode]->id;
						}

						$app->enqueueMessage(Text::_('OSM_SCHEDULE_CONTENT_LOCKED'), 'warning');
						$app->redirect(Route::_('index.php?Itemid=' . $redirectMenuItem));
					}
				}
				else
				{
					throw new \Exception(Text::_('OSM_SCHEDULE_CONTENT_LOCKED'), 403);
				}
			}
		}
	}

	/**
	 * Display form allows users to change settings on subscription plan add/edit screen
	 *
	 * @param   \OSMembershipTablePlan  $row
	 */
	private function drawSettingForm($row)
	{
		$numberArticlesEachTime      = $this->params->get('number_new_articles_each_time', 10);
		$form                        = Form::getInstance(
			'schedulecontent',
			JPATH_PLUGINS . '/system/schedulecontent/form/schedulecontent.xml'
		);
		$formData['schedulecontent'] = [];

		// Load existing schedule articles for this plan
		if ($row->id)
		{
			$db    = $this->getDatabase();
			$query = $db->getQuery(true)
				->select('*')
				->from('#__osmembership_schedulecontent')
				->where('plan_id = ' . $row->id)
				->order('ordering');
			$db->setQuery($query);

			foreach ($db->loadObjectList() as $scheduleContent)
			{
				$formData['schedulecontent'][] = [
					'id'           => $scheduleContent->id,
					'article_id'   => $scheduleContent->article_id,
					'number_days'  => $scheduleContent->number_days,
					'release_date' => $scheduleContent->release_date ?? '',
				];
			}
		}

		for ($i = 0; $i < $numberArticlesEachTime; $i++)
		{
			$formData['schedulecontent'][] = [
				'id'           => 0,
				'article_id'   => 0,
				'number_days'  => '',
				'release_date' => '',
			];
		}

		$form->bind($formData);

		foreach ($form->getFieldset() as $field)
		{
			echo $field->input;
		}
	}

	/**
	 * Display Display List of Documents which the current subscriber can download from his subscription
	 *
	 * @param   object  $row
	 */
	private function drawScheduleContent($row)
	{
		$subscriptions = \OSMembershipHelper::callOverridableHelperMethod('Subscription', 'getUserSubscriptionsInfo');

		if (empty($subscriptions))
		{
			return;
		}

		$accessiblePlanIds = array_keys($subscriptions);

		$db    = $this->getDatabase();
		$query = $db->getQuery(true);
		$query->select(
			'a.id, a.catid, a.title, a.alias, a.hits, a.created, a.publish_up, c.title AS category_title, b.plan_id, b.number_days'
		)
			->from('#__content AS a')
			->innerJoin('#__categories AS c ON a.catid = c.id')
			->innerJoin('#__osmembership_schedulecontent AS b ON a.id = b.article_id')
			->whereIn('b.plan_id', $accessiblePlanIds)
			->where('a.state = 1')
			->order('plan_id')
			->order('b.number_days')
			->order('b.ordering');
		$db->setQuery($query);
		$items = $db->loadObjectList();

		if (empty($items))
		{
			return;
		}

		echo \OSMembershipHelperHtml::loadCommonLayout(
			'plugins/tmpl/schedulecontent.php',
			['items' => $items, 'subscriptions' => $subscriptions, 'params' => $this->params]
		);
	}

	/**
	 * Method to check if the plugin is executable
	 *
	 * @return bool
	 */
	private function isExecutable()
	{
		if ($this->getApplication()->isClient('site') && !$this->params->get('show_on_frontend'))
		{
			return false;
		}

		return true;
	}
}