<?php namespace ProcessWire;

/**
 * ProcessWire Page Trash Process
 *
 * Provides empty trash capability. 
 * 
 * For more details about how Process modules work, please see: 
 * /wire/core/Process.php 
 * 
 * ProcessWire 3.x, Copyright 2024 by Ryan Cramer
 * https://processwire.com
 *
 */

class ProcessPageTrash extends Process {
	
	const debug = false;
	const defaultTimeLimit = 30;
	const defaultPageLimit = 0;

	public static function getModuleInfo() {
		return array(
			'title' => __('Page Trash', __FILE__), // getModuleInfo title
			'summary' => __('Handles emptying of Page trash', __FILE__), // getModuleInfo summary 
			'version' => 103, 
			'permanent' => true, 
		); 
	}

	/**
	 * Check if an empty request has been received and delete if so, otherwise render a confirmation form
	 *
	 */
	public function ___execute() {

		if(!$this->wire()->user->isSuperuser()) throw new WirePermissionException();
		$input = $this->wire()->input;
		
		$timeLimit = abs((int) $input->post('time_limit'));
		if($timeLimit > 0) $this->session->setFor($this, 'timeLimit', $timeLimit);

		if(!$input->post('submit_empty') || !$input->post('confirm_empty')) {
			// render a form showing what pages are in the trash and confirming they want to empty it
			if($input->post('submit_empty')) $this->warning($this->_('You must check the box to confirm'));
			return $this->render();
		}
		
		$this->wire()->session->CSRF->validate();
		
		$options = array(
			'verbose' => true,
			'timeLimit' => $timeLimit > 0 ? $timeLimit : self::defaultTimeLimit,
		);
		
		$result = $this->wire()->pages->emptyTrash($options);
		if(self::debug) $this->warning($result);
		$error = false;
		
		$message = sprintf($this->_n('Deleted %d page', 'Deleted %d pages', $result['numDeleted']), $result['numDeleted']);
		
		if($result['numDeleted'] && $result['pagesPerSecond'] && $result['numDeleted'] > $result['pagesPerSecond']) {
			$message .= ' ' . sprintf($this->_('(%d pages per second)'), $result['pagesPerSecond']);
		}
		
		if($result['numRemain'] > 0) {
			$message .= ' - ' . sprintf($this->_('Not all pages could be deleted (%d remain)'), $result['numRemain']);
			$error = true;
		}
		
		if($result['timeExpired']) {
			$message .= ' - ' . sprintf($this->_('Time limit reached (%d seconds)'), "$options[timeLimit]"); 
			$error = true;
		}
		
		$session = $this->wire()->session;
		
		if($error) {
			$session->warning($message);
			$session->redirect('./');
		} else {
			// redirect to admin root after emptying trash
			$session->message($message);
			$session->redirect($this->wire()->config->urls('admin'));
		}
		
		return ''; // unreachable due to redirects above
	}	

	/**
	 * Render a form showing what pages are in the trash and confirming they want to empty it
	 *
	 */
	protected function render() {
		
		$modules = $this->wire()->modules;
		$trashTotal = $this->pages->trasher()->getTrashTotal();

		/** @var InputfieldForm $form */
		$form = $modules->get("InputfieldForm"); 
		$form->attr('action', './'); 
		$form->attr('method', 'post'); 

		if(!$trashTotal) return "<h2>" . $this->_("The trash is empty") . "</h2>";

		/** @var InputfieldCheckbox $field */
		$field = $modules->get("InputfieldCheckbox"); 
		$field->attr('name', 'confirm_empty'); 
		$field->attr('value', 1); 
		$field->label2 = $this->_('Empty the trash (confirm)');
		$field->label = sprintf(
			$this->_n('Permanently delete %d page in the trash?', 'Permanently delete %d pages in the trash?', $trashTotal), 
			$trashTotal
		);
		$field->description = $this->_('Pages emptied from the trash are deleted from the database and file system, and can no longer be restored.'); 
		$field->themeOffset = 1;
		$field->icon = 'trash-o';
		if($trashTotal > 100) {
			$field->notes = $this->_("If there are too many items in the trash, you may have to empty it multiple times.");
		}
		$form->add($field);
		
		/** @var InputfieldMarkup $field */
		$field = $modules->get("InputfieldMarkup");
		$field->label = $this->_('Pages in the trash');
		$field->icon = 'list';
		$field->collapsed = Inputfield::collapsedYes;
		/** @var ProcessPageList $pageList */
		$pageList = $this->modules->get('ProcessPageList');
		$pageList->set('id', $this->config->trashPageID);
		$pageList->set('showRootPage', false);
		$field->value = $pageList->execute();
		$field->themeOffset = 1;
		$form->add($field);
		
		/** @var InputfieldInteger $f */
		$f = $modules->get('InputfieldInteger');
		$f->attr('name', 'time_limit');
		$f->label = $this->_('Time limit (in seconds)');
		$timeLimit = (int) $this->session->getFor($this, 'timeLimit');
		$f->attr('value', $timeLimit > 0 ? $timeLimit : self::defaultTimeLimit);
		$f->icon = 'clock-o';
		$f->collapsed = Inputfield::collapsedYes;
		$form->add($f);

		/** @var InputfieldSubmit $field */
		$field = $modules->get("InputfieldSubmit"); 
		$field->attr('name', 'submit_empty'); 
		$field->showInHeader(true);	
		$field->icon = 'trash';
		$form->add($field);
		
		/** @var InputfieldButton $field */
		$field = $modules->get("InputfieldButton");
		$field->attr('name', 'submit_cancel');
		$field->setSecondary(true);
		$field->value = $this->_('Cancel');
		$field->href = $this->wire()->config->urls->admin;
		$field->icon = 'times';
		$form->add($field); 

		return $form->render();		
	}
}
