<?php
/**
* This file is part of contao-community-alliance/contao-clipboard-bundle.
*
* (c) 2013 MEN AT WORK.
* (c) 2021 The CCA team.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* This project is provided in good faith and hope to be usable by anyone.
*
* @package Clipboard
* @author Ingolf Steinhardt <info@e-spin.de>
* @copyright 2013 MEN AT WORK.
* @copyright 2021 The CCA team.
* @license https://spdx.org/licenses/LGPL-3.0-or-later.html LGPL-3.0-or-later
* @filesource
*/
namespace ContaoCommunityAlliance\ClipboardBundle;
use Contao\BackendTemplate;
use Contao\BackendUser;
use Contao\Environment;
use Contao\Input;
use Contao\Session;
use ContaoCommunityAlliance\ClipboardBundle\Helper\Base as HelperBase;
use ContaoCommunityAlliance\ClipboardBundle\Helper\Database as HelperDatabase;
use ContaoCommunityAlliance\ClipboardBundle\Xml\Base as XmlBase;
/**
* Class Clipboard
*/
class Clipboard
{
/**
* Contains some helper functions
*
* @var HelperBase
*/
private $helper;
/**
* Contains all xml specific functions and all information to the
* clipboard elements
*
* @var XmlBase
*/
private $xml;
/**
* Contains specific database request
*
* @var HelperDatabase
*/
private $database;
/**
* Session Container
*
* @var Session
*/
private $session;
/**
* Current backend user.
*
* @var BackendUser
*/
private $user;
/**
* Current backend user.
*
* @var Environment
*/
private $environment;
/**
* Prevent constructing the object (Singleton)
*
* @param HelperBase $clipboardHelper
*
* @param XmlBase $clipboardXml
*
* @param HelperDatabase $clipboardDatabase
*
*/
public function __construct(
HelperBase $clipboardHelper,
XmlBase $clipboardXml,
HelperDatabase $clipboardDatabase
) {
$this->helper = $clipboardHelper;
$this->xml = $clipboardXml;
$this->database = $clipboardDatabase;
$this->session = Session::getInstance();
$this->user = BackendUser::getInstance();
$this->environment = Environment::getInstance();
}
/**
* Get clipboard container object
*
* @return XmlBase
*
* @deprecated Use getXml instead.
*/
public function cb()
{
return $this->getXml();
}
/**
* Get clipboard container object
*
* @return XmlBase
*/
public function getXml()
{
return $this->xml;
}
/**
* Return boolean if the clipboard is for given dca and user allowed
*
* @param string $dca
*
* @return boolean
*/
public function isClipboard($dca = null): bool
{
$arrAllowedLocations = $GLOBALS['CLIPBOARD']['locations'];
if ($dca == null || !isset($GLOBALS['CLIPBOARD']['locations']) || !$this->user->clipboard) {
return false;
}
if (in_array($dca, $arrAllowedLocations)) {
if (TL_MODE == 'BE' && in_array($this->helper->getPageType(), $arrAllowedLocations)) {
return true;
}
}
return false;
}
/**
* Handle all main operations, clean up the url and redirect to itself
*/
public function init()
{
$arrSession = $this->session->get('clipboardExt');
if ($arrSession['readXML']) {
return;
}
if (stristr(
Input::get('key'),
'cl_'
)
|| Input::post('FORM_SUBMIT') == 'tl_select' && isset($_POST['cl_group'])) {
$arrUnsetParams = [];
foreach (array_keys($_GET) as $strGetParam) {
switch ($strGetParam) {
case 'key':
switch (Input::get($strGetParam)) {
// Set new favorite
case 'cl_favor':
if (strlen(Input::get('cl_id'))) {
$this->favor(Input::get('cl_id'));
}
break;
// Delete an element
case 'cl_delete':
if (strlen(Input::get('cl_id'))) {
$this->delete(Input::get('cl_id'));
}
break;
// Edit Element
case 'cl_edit':
$arrTitles = Input::post('title');
if (is_array($arrTitles)) {
$this->edit($arrTitles);
}
break;
// Create new entry
case 'cl_copy':
$this->copy();
break;
case 'cl_header_pastenew':
case 'cl_paste_into':
$this->pasteInto();
break;
case 'cl_paste_after':
$this->pasteAfter();
break;
}
$arrUnsetParams[$strGetParam] = Input::get($strGetParam);
break;
case 'act':
if (Input::get('key') != 'cl_delete') {
// Copy multi edit elements to clipboard
$ids = deserialize(Input::post('IDS'));
if (!is_array($ids) || empty($ids)) {
$this->reload();
}
$this->copy(true, $ids);
$arrUnsetParams[$strGetParam] = Input::get($strGetParam);
}
break;
case 'childs':
case 'mode':
case 'cl_id':
$arrUnsetParams[$strGetParam] = Input::get($strGetParam);
break;
}
}
foreach ($arrUnsetParams as $k => $v) {
Input::setGet($k, null);
$this->environment->request = str_replace("&$k=$v", '', $this->environment->request);
$this->environment->queryString = str_replace("&$k=$v", '', $this->environment->queryString);
$this->environment->requestUri = str_replace("&$k=$v", '', $this->environment->requestUri);
}
$arrUnsetKeyParams = [
'cl_copy',
'cl_paste_into',
'cl_paste_after'
];
if (in_array($arrUnsetParams['key'], $arrUnsetKeyParams) && $this->helper->getPageType() == 'content') {
$objArticle = $this->database->getArticleObjectFromContentId(Input::get('id'));
$strRequestWithoutId = str_replace(
substr($this->environment->request, strpos($this->environment->request, '&id')),
'',
$this->environment->request
);
\Contao\Backend::redirect($strRequestWithoutId . '&id=' . $objArticle->id);
} elseif (in_array(
$arrUnsetParams['key'],
$arrUnsetKeyParams
)
&& $this->helper->getPageType() == 'module') {
$objTheme = $this->database->getThemeObjectFromModuleId(Input::get('id'));
$strRequestWithoutId = str_replace(
substr($this->environment->request, strpos($this->environment->request, '&id')),
'',
$this->environment->request
);
\Contao\Backend::redirect($strRequestWithoutId . '&id=' . $objTheme->id);
}
\Contao\Backend::redirect($this->environment->request);
}
}
/**
* Add the Clipboard to the backend template
*
* HOOK: $GLOBALS['TL_HOOKS']['outputBackendTemplate']
*
* @param string $strContent
* @param string $strTemplate
*
* @return string
*/
public function outputBackendTemplate($strContent, $strTemplate): string
{
$this->session->set('clipboardExt', ['readXML' => false]);
if ($strTemplate == 'be_main' && $this->user->clipboard && $this->getXml()->hasElements()) {
$objTemplate = new BackendTemplate('be_clipboard');
$arrClipboard = $this->getXml()->getElements();
$objTemplate->clipboard = $arrClipboard;
$objTemplate->isContext = $this->helper->isContext();
$objTemplate->action = $this->environment->request . '&key=cl_edit';
if (!$this->helper->isContext()) {
$strContent = preg_replace('/<body.*class="/', "$0clipboard ", $strContent, 1);
}
return preg_replace('/<div.*id="container".*>/', $objTemplate->parse() . "\n$0", $strContent, 1);
}
return $strContent;
}
/**
* Prepare context if is set or disable context
*/
public function prepareContext()
{
if (!$this->helper->isContext()) {
foreach ($GLOBALS['CLIPBOARD'] as $key => $value) {
if (array_key_exists('attributes', $GLOBALS['CLIPBOARD'][$key])) {
$GLOBALS['CLIPBOARD'][$key]['attributes'] = 'onclick="Backend.getScrollOffset();"';
}
}
}
}
/**
* Paste favorite into
*/
public function pasteInto()
{
$this->getXml()->read('pasteInto', Input::get('id'));
}
/**
* Paste favorite after
*/
public function pasteAfter()
{
$this->getXml()->read('pasteAfter', Input::get('id'));
}
/**
* Delete the given element
*
* @param string $hash
*/
public function delete($hash)
{
$this->getXml()->deleteFile($hash);
}
/**
* Make the given element favorit
*
* @param string $hash
*/
public function favor($hash)
{
$this->getXml()->setFavor($hash);
}
/**
* Rename all given clipboard titles
*
* @param array $arrTitles
*/
public function edit($arrTitles)
{
$this->getXml()->editTitle($arrTitles);
}
/**
* Return the title for the given id
*
* @param mixed $mixedId
*
* @return string
*/
public function getTitle($mixedId)
{
$arrTitle = [];
$booClGroup = false;
if (is_array($mixedId)) {
$booClGroup = true;
}
switch ($this->helper->getPageType()) {
case 'page':
if ($booClGroup) {
$mixedId = $mixedId[0];
}
$objElem = $this->database->getPageObject($mixedId);
$arrTitle = ['title' => $objElem->title];
break;
case 'article':
$arrTitle = [
'title' => call_user_func_array([
$this->database,
'get' . $this->helper->getPageType() . 'Object'
], [$mixedId])->title
];
break;
case 'content':
if (!$booClGroup) {
$mixedTitle = $this->helper->createContentTitle($mixedId, $booClGroup);
if (!is_object($mixedTitle) && is_array($mixedTitle)) {
$arrTitle = $mixedTitle;
} else {
$arrTitle = [
'title' => $GLOBALS['TL_LANG']['MSC']['noClipboardTitle'],
'attribute' => $GLOBALS['TL_LANG']['CTE'][$mixedTitle->type][0]
];
}
} else {
$strTitle = '';
foreach ($mixedId as $intId) {
$mixedTitle = $this->helper->createContentTitle($intId, $booClGroup);
if (!is_object($mixedTitle) && is_array($mixedTitle)) {
$strTitle = $mixedTitle['title'];
break;
}
}
if (strlen($strTitle) > 0) {
$arrTitle = ['title' => $strTitle];
} else {
$arrTitle = ['title' => $GLOBALS['TL_LANG']['MSC']['noClipboardTitle']];
}
}
break;
case 'module':
$objElem = $this->database->getModuleObject($mixedId);
$arrTitle = ['title' => $objElem->name];
break;
default:
$arrTitle = ['title' => $GLOBALS['TL_LANG']['MSC']['noClipboardTitle']];
}
$arrTitle['title'] = \StringUtil::substr($arrTitle['title'], '24');
return $arrTitle;
}
/**
* Copy element to clipboard and write xml
*
* @param bool $booClGroup
* @param array $ids
*/
public function copy(bool $booClGroup, array $ids = [])
{
$arrSet = [
'user_id' => $this->user->id,
'table' => $this->helper->getDatabasePageType()
];
if ($booClGroup == true && count($ids) > 1) {
$arrSet['childs'] = 0;
$arrSet['elem_id'] = $ids;
$arrSet['grouped'] = true;
$arrSet['groupCount'] = count($ids);
$arrSet = array_merge($arrSet, $this->getTitle($ids));
} else {
if (count($ids) == 1) {
$intId = $ids[0];
} else {
$intId = Input::get('id');
}
$arrSet['childs'] = ((Input::get('childs') == 1) ? 1 : 0);
$arrSet['elem_id'] = $intId;
$arrSet['grouped'] = false;
$arrSet['groupCount'] = 0;
$arrSet = array_merge($arrSet, $this->getTitle($intId));
}
if (!$arrSet['attribute']) {
$arrSet['attribute'] = '';
}
$this->getXml()->write($arrSet);
}
}