View file phpbb/ads/controller/admin_input.php

File size: 8.62Kb
<?php
/**
 *
 * Advertisement management. An extension for the phpBB Forum Software package.
 *
 * @copyright (c) 2017 phpBB Limited <https://www.phpbb.com>
 * @license GNU General Public License, version 2 (GPL-2.0)
 *
 */

namespace phpbb\ads\controller;

use phpbb\ads\ext;

/**
 * Admin input
 */
class admin_input
{
	/** @var \phpbb\user */
	protected $user;

	/** @var \phpbb\user_loader */
	protected $user_loader;

	/** @var \phpbb\language\language */
	protected $language;

	/** @var \phpbb\request\request */
	protected $request;

	/** @var \phpbb\ads\banner\banner */
	protected $banner;

	/** @var array Form validation errors */
	protected $errors = array();

	/**
	 * Constructor
	 *
	 * @param \phpbb\user              $user        User object
	 * @param \phpbb\user_loader       $user_loader User loader object
	 * @param \phpbb\language\language $language    Language object
	 * @param \phpbb\request\request   $request     Request object
	 * @param \phpbb\ads\banner\banner $banner      Banner upload object
	 */
	public function __construct(\phpbb\user $user, \phpbb\user_loader $user_loader, \phpbb\language\language $language, \phpbb\request\request $request, \phpbb\ads\banner\banner $banner)
	{
		$this->user = $user;
		$this->user_loader = $user_loader;
		$this->language = $language;
		$this->request = $request;
		$this->banner = $banner;

		add_form_key('phpbb_ads');
	}

	/**
	 * Gets all errors
	 *
	 * @return	array	Errors
	 */
	public function get_errors()
	{
		return $this->errors;
	}

	/**
	 * Returns number of errors.
	 *
	 * @return	int	Number of errors
	 */
	public function has_errors()
	{
		return count($this->errors);
	}

	/**
	 * Get admin form data.
	 *
	 * @return	array	Form data
	 */
	public function get_form_data()
	{
		$data = array(
			'ad_name'         	=> $this->request->variable('ad_name', '', true),
			'ad_note'         	=> $this->request->variable('ad_note', '', true),
			'ad_code'         	=> $this->request->variable('ad_code', '', true),
			'ad_enabled'      	=> $this->request->variable('ad_enabled', 0),
			'ad_locations'    	=> $this->request->variable('ad_locations', array('')),
			'ad_start_date'     => $this->request->variable('ad_start_date', ''),
			'ad_end_date'     	=> $this->request->variable('ad_end_date', ''),
			'ad_priority'     	=> $this->request->variable('ad_priority', ext::DEFAULT_PRIORITY),
			'ad_content_only'	=> $this->request->variable('ad_content_only', 0),
			'ad_views_limit'  	=> $this->request->variable('ad_views_limit', 0),
			'ad_clicks_limit' 	=> $this->request->variable('ad_clicks_limit', 0),
			'ad_owner'        	=> $this->request->variable('ad_owner', '', true),
			'ad_groups'			=> $this->request->variable('ad_groups', array(0)),
			'ad_centering'		=> $this->request->variable('ad_centering', true),
		);

		// Validate form key
		if (!check_form_key('phpbb_ads'))
		{
			$this->errors[] = 'FORM_INVALID';
		}

		// Validate each property. Some validators update the property value. Errors are added to $this->errors.
		foreach ($data as $prop_name => $prop_val)
		{
			$method = 'validate_' . $prop_name;
			if (method_exists($this, $method))
			{
				$data[$prop_name] = $this->{$method}($prop_val);
			}
		}

		// Make sure start date is sooner than end date
		if ($data['ad_start_date'] != 0 && $data['ad_end_date'] != 0 && $data['ad_start_date'] > $data['ad_end_date'])
		{
			$this->errors[] = $this->language->lang('END_DATE_TOO_SOON');
		}

		return $data;
	}

	/**
	 * Upload image and return updated ad code or <img> of new banner when using ajax.
	 *
	 * @param	 string	 $ad_code	 Current ad code
	 * @return	 string	 \phpbb\json_response when request is ajax or updated ad code otherwise.
	 */
	public function banner_upload($ad_code)
	{
		try
		{
			$this->banner->create_storage_dir();
			$realname = $this->banner->upload();

			$banner_html = '<img src="' . generate_board_url() . '/images/phpbb_ads/' . $realname . '" />';

			if ($this->request->is_ajax())
			{
				$this->send_ajax_response(true, $banner_html);
			}

			$ad_code = ($ad_code ? $ad_code . "\n\n" : '') . $banner_html;
		}
		catch (\phpbb\exception\runtime_exception $e)
		{
			$this->banner->remove();

			if ($this->request->is_ajax())
			{
				$this->send_ajax_response(false, $this->language->lang($e->getMessage()));
			}

			$this->errors[] = $this->language->lang($e->getMessage());
		}

		return $ad_code;
	}

	/**
	 * Validate advertisement name
	 *
	 * Ad name is required and must not be empty. Ad name must
	 * also be less than 255 characters.
	 *
	 * @param string $ad_name Advertisement name
	 * @return string Advertisement name
	 */
	protected function validate_ad_name($ad_name)
	{
		if ($ad_name === '')
		{
			$this->errors[] = 'AD_NAME_REQUIRED';
		}

		if (truncate_string($ad_name, ext::MAX_NAME_LENGTH) !== $ad_name)
		{
			$this->errors[] = $this->language->lang('AD_NAME_TOO_LONG', ext::MAX_NAME_LENGTH);
		}

		return $ad_name;
	}

	/**
	 * Validate advertisement code
	 *
	 * Ad code should not contain 4-byte Emoji characters.
	 *
	 * @param string $ad_code Advertisement code
	 * @return string Advertisement code
	 */
	protected function validate_ad_code($ad_code)
	{
		if (preg_match_all('/[\x{10000}-\x{10FFFF}]/u', $ad_code, $matches))
		{
			$characters = implode(' ', $matches[0]);
			$this->errors[] = $this->language->lang('AD_CODE_ILLEGAL_CHARS', $characters);
		}

		return $ad_code;
	}

	/**
	 * Validate advertisement start date
	 *
	 * @param string $start_date Advertisement start date
	 * @return int The start date converted to timestamp if valid, otherwise 0.
	 */
	protected function validate_ad_start_date($start_date)
	{
		return $this->validate_date($start_date, 'START');
	}

	/**
	 * Validate advertisement end date.
	 *
	 * @param string $end_date Advertisement end date
	 * @return int The end date converted to timestamp if valid, otherwise 0.
	 */
	protected function validate_ad_end_date($end_date)
	{
		return $this->validate_date($end_date, 'END');
	}

	/**
	 * Validate advertisement priority
	 *
	 * Ad priority must be an integer between 1 and 10.
	 *
	 * @param int $ad_priority Advertisement priority
	 * @return int Advertisement priority
	 */
	protected function validate_ad_priority($ad_priority)
	{
		if ($ad_priority < 1 || $ad_priority > 10)
		{
			$this->errors[] = 'AD_PRIORITY_INVALID';
		}

		return $ad_priority;
	}

	/**
	 * Validate advertisement views limit
	 *
	 * Clicks must be a positive integer.
	 *
	 * @param int $ad_views_limit Advertisement views limit
	 * @return int Advertisement views limit
	 */
	protected function validate_ad_views_limit($ad_views_limit)
	{
		if ($ad_views_limit < 0)
		{
			$this->errors[] = 'AD_VIEWS_LIMIT_INVALID';
		}

		return $ad_views_limit;
	}

	/**
	 * Validate advertisement clicks limit
	 *
	 * Clicks must be a positive integer.
	 *
	 * @param int $ad_clicks_limit Advertisement clicks limit
	 * @return int Advertisement clicks limit
	 */
	protected function validate_ad_clicks_limit($ad_clicks_limit)
	{
		if ($ad_clicks_limit < 0)
		{
			$this->errors[] = 'AD_CLICKS_LIMIT_INVALID';
		}

		return $ad_clicks_limit;
	}

	/**
	 * Validate advertisement owner
	 *
	 * If ad owner name given, get their ID. If the ID returned is ANONYMOUS,
	 * set an error because the user name given doesn't exist.
	 *
	 * @param string $ad_owner User name
	 * @return int User id if user exists, otherwise 0.
	 */
	protected function validate_ad_owner($ad_owner)
	{
		$user_id = 0;
		if (!empty($ad_owner) && ANONYMOUS === ($user_id = (int) $this->user_loader->load_user_by_username($ad_owner)))
		{
			$this->errors[] = 'AD_OWNER_INVALID';
		}

		return ANONYMOUS !== $user_id ? $user_id : 0;
	}

	/**
	 * Send ajax response
	 *
	 * @param bool $success Is request successful?
	 * @param string $text Text to return
	 */
	protected function send_ajax_response($success, $text)
	{
		$json_response = new \phpbb\json_response;
		$json_response->send(array(
			'success'	=> $success,
			'title'		=> $this->language->lang('INFORMATION'),
			'text'		=> $text,
		));
	}

	/**
	 * Validate advertisement date
	 *
	 * The date must use the expected format of YYYY-MM-DD.
	 * If the date is valid, convert it to a timestamp and then
	 * make sure the timestamp is less than the current time.
	 *
	 * @param string $date Advertisement date
	 * @return int The date converted to timestamp if valid, otherwise 0.
	 */
	protected function validate_date($date, $type)
	{
		$timestamp = 0;
		if (preg_match('#^\d{4}-\d{2}-\d{2}$#', $date))
		{
			$timestamp = (int) $this->user->get_timestamp_from_format(ext::DATE_FORMAT, $date);

			if ($timestamp < time())
			{
				$this->errors[] = 'AD_' . $type . '_DATE_INVALID';
			}
		}
		else if ($date !== '')
		{
			$this->errors[] = 'AD_' . $type . '_DATE_INVALID';
		}

		return $timestamp;
	}
}