controller/acp_controller.php
<?php
/**
*
* phpBB Media Embed PlugIn extension for the phpBB Forum Software package.
*
* @copyright (c) 2016 phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
*/
namespace phpbb\mediaembed\controller;
use phpbb\config\config;
use phpbb\config\db_text;
use phpbb\language\language;
use phpbb\log\log;
use phpbb\mediaembed\cache\cache as media_cache;
use phpbb\request\request;
use phpbb\template\template;
use phpbb\textformatter\s9e\factory as textformatter;
use phpbb\user;
/**
* phpBB Media Embed ACP module controller.
*/
class acp_controller implements acp_controller_interface
{
/** @var config $config */
protected $config;
/** @var db_text $config_text */
protected $config_text;
/** @var language $language */
protected $language;
/** @var log $log */
protected $log;
/** @var media_cache $media_cache */
protected $media_cache;
/** @var request $request */
protected $request;
/** @var template $template */
protected $template;
/** @var textformatter $textformatter */
protected $textformatter;
/** @var user $user */
protected $user;
/** @var array $enabled_sites */
protected $enabled_sites;
/** @var string $u_action */
public $u_action;
/** @var array An array of errors */
protected $errors = [];
/**
* Constructor
*/
public function __construct(config $config, db_text $config_text, language $language, log $log, media_cache $media_cache, request $request, template $template, textformatter $textformatter, user $user)
{
$this->config = $config;
$this->config_text = $config_text;
$this->language = $language;
$this->log = $log;
$this->media_cache = $media_cache;
$this->request = $request;
$this->template = $template;
$this->textformatter = $textformatter;
$this->user = $user;
$this->language->add_lang('acp', 'phpbb/mediaembed');
}
/**
* Set page url
*
* @param string $u_action Custom form action
*/
public function set_page_url($u_action)
{
$this->u_action = $u_action;
}
/**
* Add settings template vars to the form
*/
public function display_settings()
{
$this->template->assign_vars([
'S_MEDIA_EMBED_BBCODE' => $this->config['media_embed_bbcode'],
'S_MEDIA_EMBED_ALLOW_SIG' => $this->config['media_embed_allow_sig'],
'S_MEDIA_EMBED_PARSE_URLS' => $this->config['media_embed_parse_urls'],
'S_MEDIA_EMBED_ENABLE_CACHE' => $this->config['media_embed_enable_cache'],
'S_MEDIA_EMBED_FULL_WIDTH' => $this->config['media_embed_full_width'],
'S_MEDIA_EMBED_MAX_WIDTHS' => $this->get_media_embed_max_width(),
'U_ACTION' => $this->u_action,
]);
}
/**
* Add manage sites template vars to the form
*/
public function display_manage()
{
$this->template->assign_vars([
'MEDIA_SITES' => $this->get_sites(),
'U_ACTION' => $this->u_action,
'ERRORS' => $this->errors,
]);
}
/**
* Save settings data to the database
*
* @return array Message and code for trigger error
*/
public function save_settings()
{
$this->config->set('media_embed_bbcode', $this->request->variable('media_embed_bbcode', 0));
$this->config->set('media_embed_allow_sig', $this->request->variable('media_embed_allow_sig', 0));
$this->config->set('media_embed_parse_urls', $this->request->variable('media_embed_parse_urls', 0));
$this->config->set('media_embed_enable_cache', $this->request->variable('media_embed_enable_cache', 0));
$this->config->set('media_embed_full_width', $this->request->variable('media_embed_full_width', 0));
$this->set_media_embed_max_width();
$this->media_cache->purge_textformatter_cache();
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PHPBB_MEDIA_EMBED_SETTINGS');
if (count($this->errors))
{
return [
'code' => E_USER_WARNING,
'message' => $this->language->lang('ACP_MEDIA_ERROR_MSG', implode('<br>', $this->errors))
];
}
return [
'code' => E_USER_NOTICE,
'message' => $this->language->lang('CONFIG_UPDATED')
];
}
/**
* Save site managed data to the database
*
* @return array Message and code for trigger error
*/
public function save_manage()
{
$this->config_text->set('media_embed_sites', json_encode($this->request->variable('mark', [''])));
$this->media_cache->purge_textformatter_cache();
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PHPBB_MEDIA_EMBED_MANAGE');
return [
'code' => E_USER_NOTICE,
'message' => $this->language->lang('CONFIG_UPDATED')
];
}
/**
* Purge all Media Embed cache files
*/
public function purge_mediaembed_cache()
{
$this->media_cache->purge_mediaembed_cache();
$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PHPBB_MEDIA_EMBED_CACHE_PURGED');
return [
'code' => E_USER_NOTICE,
'message' => $this->language->lang('PURGE_CACHE_SUCCESS')
];
}
/**
* Get a list of available sites
*
* @return array An array of available sites
*/
protected function get_sites()
{
$sites = [];
$configurator = $this->textformatter->get_configurator();
foreach ($configurator->MediaEmbed->defaultSites as $siteId => $siteConfig)
{
$disabled = isset($configurator->BBCodes[$siteId]);
$sites[$siteId] = [
'id' => $siteId,
'name' => $siteConfig['name'],
'title' => $this->language->lang($disabled ? 'ACP_MEDIA_SITE_DISABLED' : 'ACP_MEDIA_SITE_TITLE', $siteId),
'enabled' => in_array($siteId, $this->get_enabled_sites()),
'disabled' => $disabled,
];
}
ksort($sites);
$this->errors = array_diff($this->get_enabled_sites(), array_keys($sites));
return $sites;
}
/**
* Get enabled media sites stored in the database
*
* @return array An array of enabled sites
*/
protected function get_enabled_sites()
{
if ($this->enabled_sites === null)
{
$sites = json_decode($this->config_text->get('media_embed_sites'), true);
$this->enabled_sites = is_array($sites) ? $sites : [];
}
return $this->enabled_sites;
}
/**
* Store the media embed max width value to the config text as JSON,
* with some basic input validation and array formatting.
*/
protected function set_media_embed_max_width()
{
$input = $this->request->variable('media_embed_max_width', '');
if ($input)
{
$lines = array_unique(explode("\n", $input));
foreach ($lines as $key => $line)
{
$parts = explode(':', $line);
if (count($parts) !== 2)
{
unset($lines[$key]);
continue;
}
$lines[$key] = array_combine(['site', 'width'], array_map('trim', $parts));
}
$input = json_encode(array_filter($lines, [$this, 'validate']));
}
$this->config_text->set('media_embed_max_width', strtolower($input));
}
/**
* Get the stored media embed max width data from config text and convert
* from JSON to the formatting used in the ACP textarea field.
*
* @return string
*/
protected function get_media_embed_max_width()
{
$config = json_decode($this->config_text->get('media_embed_max_width'), true);
if ($config)
{
foreach ($config as &$item)
{
$item = implode(':', $item);
}
unset($item);
}
return $config ? implode("\n", $config) : '';
}
/**
* Validate the input for media embed max widths
* 'site' key value should be a word
* 'width' key value should be a number appended with either px or %
*
* @param array $input The array to check
* @return bool True if array contains valid values, false if not
* @throws \Exception
*/
protected function validate($input)
{
// First, lets get all the available media embed site IDs
static $default_sites;
if (null === $default_sites)
{
$configurator = $this->textformatter->get_configurator();
$default_sites = array_keys(iterator_to_array($configurator->MediaEmbed->defaultSites));
}
// Next create an array to hold any errors
$errors = [];
// Check to see if the site id provided exists in Media Embed
if (!in_array($input['site'], $default_sites))
{
$errors[] = $this->language->lang('ACP_MEDIA_INVALID_SITE', $input['site'], $input['width']);
}
// Check to see if the width provided is a valid number followed px or %
if (!preg_match('/^\d+(?:%|px)$/', $input['width']))
{
$errors[] = $this->language->lang('ACP_MEDIA_INVALID_WIDTH', $input['site'], $input['width']);
}
// Update the errors object with any new errors
$this->errors = array_merge($this->errors, $errors);
return empty($errors);
}
}