An error occurred while loading the file. Please try again.
-
Côme Chilliet authored
This replaces save_object and execute methods by 3 methods: readPost - Reads POST data update - Update object state render - Render HTML UI The point is to avoid reading POST and rendering HTML when this is not needed (when doing stuff through the webservice for instance). It’s also more consisent across FD with all classes handling some kind of dialog implementing the new interface FusionDirectoryDialog which makes sure these 3 methods are implemented. issue #6072
Unverified94eaa6ba
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2017 FusionDirectory
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*!
* \file class_CopyPasteHandler.inc
* Source code for class CopyPasteHandle
*/
/*!
* \brief This class contains all function to copy and paste
*/
class CopyPasteHandler implements FusionDirectoryDialog
{
var $current = FALSE;
/*!
* \brief This array contains all dns of the currently copied objects
*/
protected $objectList = [];
/*!
* \brief This array contains all remaining objects to paste
*/
protected $queue = [];
/*!
* \brief The dn of the last edited object
*/
protected $lastdn = '';
protected $disallowed_objects = [];
protected $objects_to_fix = [];
protected $clean_objects = [];
protected $require_update = FALSE;
/*!
* \brief Create CP handler
*/
function __construct ()
{
}
/*!
* \brief Entry entry to Copy & Paste queue.
* A Queue entry is represented as follows.
* array['method'] - 'copy' or 'cut'
* array['dn'] - the dn of the object added to the queue
* array['type'] - Object type
*
* \param String $dn The dn of the object added to the queue
*
* \param String $action Copy or Cut
*
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
* \param String $type the type of the object
*/
function add_to_queue ($dn, $action, $type)
{
logging::debug(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $dn, 'add_to_queue');
if (!in_array($action, ['cut','copy'])) {
trigger_error(sprintf('Specified action "%s" does not exists for copy & paste.', $action));
return FALSE;
}
$tmp = [];
$tmp['method'] = $action;
$tmp['dn'] = $dn;
$tmp['type'] = $type;
$infos = objects::infos($type);
$tmp['aclCategory'] = $infos['aclCategory'];
$tmp['mainTab'] = $infos['mainTab'];
$tmp['parent'] = NULL;
$this->queue[] = $tmp;
if ($action == 'copy') {
$this->objectList[] = $tmp;
}
$this->require_update = TRUE;
return TRUE;
}
/*!
* \brief This removes all objects from queue.
* Remove hdd dumps of current entries too.
* Remove entries older than 24 hours.
*/
function cleanup_queue ()
{
$this->current = FALSE;
$this->require_update = TRUE;
$this->queue = [];
$this->objectList = [];
}
/*!
* \brief This resets the queue to allow pasting again.
*/
function resetPaste ()
{
$this->current = FALSE;
$this->require_update = TRUE;
$this->queue = $this->objectList;
}
/*!
* \brief Check if there are still entries the object queue
*/
function entries_queued ()
{
return ((count($this->queue) > 0) || ($this->current !== FALSE));
}
/*!
* \brief Paste one entry from LDAP
*/
protected function load_entry_from_ldap ($entry)
{
logging::debug(DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $entry['dn'], 'load_entry_from_ldap');
if (!isset($entry['tab_class']) && !isset($entry['type'])) {
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
return [];
}
$entry['object'] = objects::open($entry['dn'], $entry['type']);
if ($entry['parent'] !== NULL) {
$entry['object']->parent = $entry['parent'];
}
if ($entry['method'] == 'copy') {
$entry['object']->resetCopyInfos();
}
logging::log('copy', $entry['method'], $entry['dn'], [], '');
$entry['object']->resetBase();
return $entry;
}
public function update(): bool
{
$ui = get_userinfo();
/* Check which entries can be pasted directly.
* Create a list of all entries that can be pasted directly.
*/
if ($this->require_update) {
$this->clean_objects = [];
$this->objects_to_fix = [];
$this->disallowed_objects = [];
/* Put each queued object in one of the above arrays */
foreach ($this->queue as $key => $entry) {
/* Update entries on demand */
if (!isset($entry['object'])) {
$entry = $this->load_entry_from_ldap($entry);
$this->queue[$key] = $entry;
}
/* Retrieve ACL infos */
$copy_acl = $ui->is_copyable($entry['dn'], $entry['aclCategory']);
$cut_acl = $ui->is_cutable($entry['dn'], $entry['aclCategory'], $entry['mainTab']);
/* Check permissions */
if ((($entry['method'] == 'copy') && !$copy_acl)
|| (($entry['method'] == 'cut') && !$cut_acl)) {
$this->disallowed_objects[$key] = $entry;
} else {
$this->clean_objects[$key] = $entry;
}
}
if (count($this->disallowed_objects)) {
$dns = [];
foreach ($this->disallowed_objects as $entry) {
$dns[] = $entry['dn'];
}
$error = new FusionDirectoryPermissionError(msgPool::permCreate($dns));
$error->display();
}
$this->require_update = FALSE;
}
/* Save objects that can be pasted directly */
if (count($this->clean_objects)) {
foreach ($this->clean_objects as $key => $entry) {
$this->current = $entry;
$errors = $this->current['object']->save();
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
if (empty($errors)) {
$this->current_saved();
/* Remove from queue -> avoid saving twice */
unset($this->queue[$key]);
} else {
$this->objects_to_fix[$key] = $entry;
}
unset($this->clean_objects[$key]);
}
$this->current = FALSE;
}
/* Save edited entry and force loading new one */
if (isset($this->current['object'])) {
$this->current['object']->readPost();
$this->current['object']->update();
/* Save current object if edition is finished */
if (!$this->current['object']->dialogOpened() && isset($_POST['edit_finish'])) {
$errors = $this->current['object']->save();
if (empty($errors)) {
$this->current_saved();
} else {
msg_dialog::displayChecks($errors);
}
}
}
return TRUE;
}
/*!
* \brief Displays a dialog which allows the user to fix all dependencies of this object.
* Create unique names, ids, or what ever
*/
public function render (): string
{
/* Display a list of all pastable entries */
if ($this->current || count($this->objects_to_fix)) {
if (!$this->current) {
$key = key($this->objects_to_fix);
if ($key !== NULL) {
$this->current = $this->objects_to_fix[$key];
unset($this->objects_to_fix[$key]);
unset($this->queue[$key]);
}
}
if ($this->current) {
$display = $this->current['object']->render();
if (!$this->current['object']->dialogOpened()) {
// Display ok, (apply) and cancel buttons
$display .= '<p class="plugbottom">'."\n";
$display .= '<input type="submit" name="edit_finish" style="width:80px" value="'.msgPool::okButton().'"/>'."\n";
$display .= " \n";
$display .= '<input type="submit" formnovalidate="formnovalidate" name="abort_current_cut-copy_operation" value="'.msgPool::cancelButton().'"/>'."\n";
$display .= '<input type="submit" formnovalidate="formnovalidate" name="abort_all_cut-copy_operations" value="'._('Cancel all').'"/>'."\n";
$display .= '</p>';
}
return $display;
}
}
return '';
}
private function current_saved ()
{
$this->lastdn = $this->current['object']->dn;
logging::log('copy', 'paste', $this->lastdn);
$this->handleReferences();
$this->current = FALSE;
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
}
/*!
* \brief Get the last endited entry
*
* \return the dn of the last edited entry
*/
function last_entry ()
{
return $this->lastdn;
}
/*!
* \brief Save new values posted by copy & paste dialog
*/
public function readPost ()
{
if (isset($_POST['abort_current_cut-copy_operation'])) {
$this->current = FALSE;
}
if (isset($_POST['abort_all_cut-copy_operations'])) {
$this->cleanup_queue();
$this->current = FALSE;
}
}
function handleReferences ()
{
$dst_dn = $this->current['object']->dn;
$src_dn = $this->current['dn'];
$this->current['object']->getBaseObject()->handleForeignKeys(
$src_dn,
$dst_dn,
($this->current['method'] == 'cut' ? 'move' : 'copy')
);
}
/*!
* \brief Generate the paste icon for headpages
*
* \return the paste icon for headpages
*/
function generatePasteIcon ()
{
$Copy_Paste = " <img class='center' src='images/lists/seperator.png' alt='' height='16' width='1'> ";
if ($this->entries_queued()) {
$Copy_Paste .= "<input type='image' name='editPaste' class='center'
src='geticon.php?context=actions&icon=edit-paste&size=16' alt='"._("Paste")."'> ";
} else {
$Copy_Paste .= "<img class='center' src='geticon.php?context=actions&icon=edit-paste&size=16&disabled=1' alt=\""._("Cannot paste")."\"> ";
}
return $Copy_Paste;
}
}