<?php if (!defined('FW')) die('Forbidden');

class FW_Extension_Backups extends FW_Extension {
	/**
	 * @var _FW_Ext_Backups_Module_Tasks
	 */
	private $tasks;

	/**
	 * @return _FW_Ext_Backups_Module_Tasks
	 */
	public function tasks() {
		return $this->tasks;
	}

	/**
	 * @var _FW_Ext_Backups_Module_Schedule
	 */
	private $schedule;

	/**
	 * @return _FW_Ext_Backups_Module_Schedule
	 */
	public function schedule() {
		return $this->schedule;
	}

	private static $wp_ajax_action_status  = 'fw:ext:backups:status';
	private static $wp_ajax_action_backup  = 'fw:ext:backups:backup';
	private static $wp_ajax_action_restore = 'fw:ext:backups:restore';
	private static $wp_ajax_action_delete  = 'fw:ext:backups:delete';
	private static $wp_ajax_action_cancel  = 'fw:ext:backups:cancel';

	// Cactus custom create demo
	private static $wp_ajax_action_create  = 'fw:ext:backups:create';
	private static $wp_ajax_action_create_remote  = 'fw:ext:backups:create_remote';

	private static $wp_ajax_action_test    = 'fw:ext:backups:test';

	private static $download_GET_parameter = 'download-archive';

	private static $download_GET_demo_parameter = 'download-demo-archive';

	/**
	 * Also can be used as "is current user allowed to make backups?"
	 * @return string
	 */
	public function get_capability() {
		/**
		 * https://codex.wordpress.org/Roles_and_Capabilities#Capability_vs._Role_Table
		 * Should work on both single and multi-site
		 */
		return 'export';
	}

	/**
	 * @param int $sum Since 2.0.16
	 * @return int
	 */
	public function get_timeout($sum = 0) {
		$timeout = (int)ini_get('max_execution_time');

		/**
		 * Fix timeout value
		 * For e.g. timeout 0 messes up the tasks execution verification logic
		 */
		if ($timeout < 1 || $timeout > $this->get_config('max_timeout')) {
			$timeout = $this->get_config('max_timeout');
		}

		return max($timeout + $sum, 1); // Prevent negative or 0 value
	}

	/**
	 * If a task step execution takes more that this amount of second, then perhaps it is something wrong.
	 * @return int
	 * @since 2.0.14
	 */
	public function get_task_step_execution_threshold() {
		return 30; // http://php.net/manual/en/info.configuration.php#ini.max-execution-time
	}

	public function get_page_slug() {
		return 'fw-backups';
	}

	public function get_page_url() {
		if ($this->is_disabled()) {
			return;
		}

		$rel_path = 'admin.php?page=' . urlencode( $this->get_page_slug() );

		if (is_multisite() && is_network_admin()) {
			return network_admin_url( $rel_path );
		} else {
			return admin_url( $rel_path );
		}
	}

	/**
	 * On some installations the backup actions need to be disabled for security reasons
	 * (for e.g. public testlabs for clients to test your theme and demo content install)
	 * @return bool
	 * @since 2.0.1
	 */
	public function is_disabled() {
		$cache_key = $this->get_cache_key('/disabled');

		try {
			return FW_Cache::get($cache_key);
		} catch (FW_Cache_Not_Found_Exception $e) {
			$is_disabled = (
				is_multisite() && !current_user_can('manage_network_plugins') &&
				apply_filters('fw:ext:backups:multisite_disabled', false)
			);

			FW_Cache::set($cache_key, $is_disabled);

			return $is_disabled;
		}
	}

	/**
	 * @since 2.0.22
	 * @return string Error message
	 */
	public function server_requirements_not_met() {
		if (class_exists('ZipArchive')) {
			return false;
		} else {
			return sprintf(
				__('Oops, %s requires %s but it is not enabled on your server. If you are not familiar with PHP Zip module, please contact your hosting provider.', 'fw'),
				fw_html_tag('a', array(
					'href' => function_exists('menu_page_url')
						? menu_page_url(fw()->extensions->manager->get_page_slug(), false) .'#ext-backups'
						: '#',
				), __('Unyson Backup', 'fw')),
				fw_html_tag('a', array(
					'href' => 'https://www.google.com/search#q=hosting+enable+php+zip',
					'target' => '_blank',
				), __('PHP Zip module', 'fw'))
			);
		}
	}

	protected function _init() {
		{
			if (!$this->is_disabled()) {
				add_action('admin_menu', array($this, '_action_admin_menu'));
				add_action('current_screen',  array($this, '_action_download'));
				add_action('admin_enqueue_scripts', array($this, '_action_enqueue_scripts'));

				add_action('wp_ajax_' . self::$wp_ajax_action_status,  array($this, '_action_ajax_status'));
				add_action('wp_ajax_' . self::$wp_ajax_action_backup,  array($this, '_action_ajax_backup'));
				add_action('wp_ajax_' . self::$wp_ajax_action_restore, array($this, '_action_ajax_restore'));
				add_action('wp_ajax_' . self::$wp_ajax_action_delete,  array($this, '_action_ajax_delete'));
				add_action('wp_ajax_' . self::$wp_ajax_action_cancel,  array($this, '_action_ajax_cancel'));

				// Cactus custom create demo
				add_action('wp_ajax_' . self::$wp_ajax_action_create,  array($this, '_action_ajax_create'));

				// Cactus custom create remote demo
				// add_action('wp_ajax_' . self::$wp_ajax_action_create_remote,  array($this, '_action_ajax_create_remote'));
			}

			add_action('network_admin_menu', array($this, '_action_admin_menu'));
			add_action('wp_ajax_nopriv_' . self::$wp_ajax_action_test,  array($this, '_action_ajax_test'));
		}

		$dir = dirname(__FILE__);

		// load and init modules/parts
		{
			require_once $dir .'/includes/module/class--fw-ext-backups-module.php';

			require_once $dir .'/includes/module/tasks/class--fw-ext-backups-module-tasks.php';
			$this->tasks = new _FW_Ext_Backups_Module_Tasks(self::get_access_key());

			require_once $dir .'/includes/module/schedule/class--fw-ext-backups-module-schedule.php';
			$this->schedule = new _FW_Ext_Backups_Module_Schedule(self::get_access_key());

			$this->tasks->_init();
			$this->schedule->_init();
		}

		require_once $dir .'/includes/log/init.php';
	}

	/**
	 * @var FW_Access_Key
	 */
	private static $access_key;

	/**
	 * @return FW_Access_Key
	 */
	private static function get_access_key() {
		if (empty(self::$access_key)) {
			self::$access_key = new FW_Access_Key('fw:ext:backups');
		}

		return self::$access_key;
	}

	/**
	 * @return bool
	 */
	public function is_backups_page() {
		$current_screen = get_current_screen();

		if (!$current_screen) {
			return false;
		}

		$cache_key = $this->get_cache_key('/is_backups_page');

		try {
			return FW_Cache::get($cache_key);
		} catch (FW_Cache_Not_Found_Exception $e) {
			$is = false;

			foreach (array(
				'_page_'. $this->get_page_slug(),
				'_page_'. $this->get_page_slug() .'-network',
			) as $suffix) {
				if (substr($current_screen->id, -strlen($suffix)) === $suffix) {
					$is = true;
					break;
				}
			}

			FW_Cache::set($cache_key, $is);

			return $is;
		}
	}

	public function _action_enqueue_scripts() {
		if ($this->is_backups_page()) {
			wp_enqueue_style('fw');
			wp_enqueue_media(); // needed for modal styles

			wp_enqueue_style(
				'fw-ext-backups',
				$this->get_uri('/static/style.css'),
				array('fw'),
				$this->manifest->get_version()
			);

			wp_enqueue_script(
				'fw-ext-backups',
				$this->get_uri('/static/scripts.js'),
				array('fw'),
				$this->manifest->get_version()
			);

			// truemag custom create demo localize
			wp_localize_script(
				'fw-ext-backups',
				'_fw_ext_backups_localized',
				array_merge(
					apply_filters('fw:ext:backups:script_localized_data', array()),
					array(
						'ajax_action_status'  => self::$wp_ajax_action_status,
						'ajax_action_backup'  => self::$wp_ajax_action_backup,
						'ajax_action_restore' => self::$wp_ajax_action_restore,
						'ajax_action_delete'  => self::$wp_ajax_action_delete,
						'ajax_action_cancel'  => self::$wp_ajax_action_cancel,
						'ajax_action_create'  => self::$wp_ajax_action_create,
						'ajax_action_creat_remote'=> self::$wp_ajax_action_create_remote,
						'l10n' => array(
							'abort_confirm' => __('Are you sure?', 'fw'),
						),
					)
				)
			);

			do_action('fw:ext:backups:enqueue_scripts');
		}
	}

	/**
	 * @internal
	 */
	public function _action_ajax_status() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		// in case the execution chain stopped and there is a pending task
		$this->tasks()->_request_next_step_execution(self::get_access_key());

		$is_busy = (bool)$this->tasks()->get_active_task_collection();
		$archives = $this->get_archives();

		$response = array(
			'is_busy' => $is_busy,
			'tasks_status' => array(
				'html' => $this->render_view('tasks-status', array(
					'active_task_collection' => $this->tasks()->get_active_task_collection(),
					'executing_task' => $this->tasks()->get_executing_task(),
					'pending_tasks' => $this->tasks()->get_pending_task(),
				)),
			),
			'archives' => array(
				'count' => count($archives),
				'html' => $this->render_view('archives', array(
					'archives' => $archives,
					'is_busy' => $is_busy,
				)),
			),
			'ajax_steps' => array(
				'token' => md5(
					defined('NONCE_SALT')
						? NONCE_SALT
						: $this->manifest->get_version()
				),
				'active_tasks_hash' => (($collection = $this->tasks()->get_active_task_collection())
					? md5(serialize($collection))
					: ''
				)
			),
		);

		wp_send_json_success(array_merge(
			apply_filters('fw_ext_backups_ajax_status_extra_response', array(), array('is_busy' => $is_busy)),
			$response
		));
	}

	/**
	 * @internal
	 */
	public function _action_ajax_backup() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		$this->tasks()->do_backup(
			!empty($_POST['full'])
			&&
			fw_ext_backups_current_user_can_full()
		);

		wp_send_json_success();
	}

	/**
	 * @internal
	 */
	public function _action_ajax_restore() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		$archives = $this->get_archives();

		if (
			empty($_POST['file'])
			||
			!isset($archives[ $filename = (string)$_POST['file'] ])
		) {
			wp_send_json_error(new WP_Error(
				'no_file', __('File not specified', 'fw')
			));
		}

		$fs_args = array();

		if ($archives[ $filename ]['full'] && !FW_WP_Filesystem::has_direct_access(ABSPATH)) {
			if (empty($_POST['filesystem_args'])) {
				wp_send_json_error(array(
					'message' => esc_html__('Filesystem access required', 'fw'),
					'request_fs' => true,
				));
			} else {
				$fs_args = $_POST['filesystem_args'];

				if (
					is_array($_POST['filesystem_args']) &&
					isset($fs_args['hostname']) && is_string($fs_args['hostname']) &&
					isset($fs_args['username']) && is_string($fs_args['username']) &&
					isset($fs_args['password']) && is_string($fs_args['password']) &&
					isset($fs_args['connection_type']) && is_string($fs_args['connection_type'])
				) {
					$fs_args = array(
						'hostname' => $fs_args['hostname'],
						'username' => $fs_args['username'],
						'password' => $fs_args['password'],
						'connection_type' => $fs_args['connection_type'],
					);

					if (!WP_Filesystem($fs_args, ABSPATH)) {
						wp_send_json_error(array(
							'message' => esc_html__('Invalid filesystem credentials', 'fw')
						));
					}
				} else {
					wp_send_json_error(array(
						'message' => esc_html__('Invalid filesystem credentials', 'fw')
					));
				}
			}
		}

		$this->tasks()->do_restore(
			$archives[ $filename ]['full'] && fw_ext_backups_current_user_can_full(),
			$archives[ $filename ]['path'],
			$fs_args
		);

		wp_send_json_success();
	}

	/**
	 * @internal
	 */
	public function _action_ajax_delete() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		$archives = $this->get_archives();

		if (
			empty($_POST['file'])
			||
			!isset($archives[ $filename = (string)$_POST['file'] ])
		) {
			wp_send_json_error(new WP_Error(
				'no_file', __('File not specified', 'fw')
			));
		}


		$current_theme = wp_get_theme();
		$text_domain = $current_theme->get('TextDomain');
		$folder_name = str_replace( '.zip', '', $filename );
		$downloadPath = truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/' . $folder_name;
		$this->_delete_demo_folder( $downloadPath );
		
		if (@unlink($archives[ $filename ]['path'])) {
			wp_send_json_success();
		} else {
			wp_send_json_error();
		}
	}

	public function _delete_demo_folder( $path ) {
		if (is_dir($path) === true)
		    {
		        $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::CHILD_FIRST);

		        foreach ($files as $file)
		        {
		            if (in_array($file->getBasename(), array('.', '..')) !== true)
		            {
		                if ($file->isDir() === true)
		                {
		                    rmdir($file->getPathName());
		                }

		                else if (($file->isFile() === true) || ($file->isLink() === true))
		                {
		                    unlink($file->getPathname());
		                }
		            }
		        }

		        return rmdir($path);
		    }

		    else if ((is_file($path) === true) || (is_link($path) === true))
		    {
		        return unlink($path);
		    }

		    return false;
	}

	/**
	 * @internal
	 * Cactus custom create demo
	 */
	public function _action_ajax_create() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		$archives = $this->get_archives();

		if (
			empty($_POST['file'])
			||
			!isset($archives[ $filename = (string)$_POST['file'] ])
		) {
			wp_send_json_error(new WP_Error(
				'no_file', __('File not specified', 'fw')
			));
		}

		if ( $archives ) {
			$current_theme = wp_get_theme();
			$text_domain = $current_theme->get('TextDomain');

			$zip = new ZipArchive;
			$path = $archives[ $filename ][ 'path' ];

			$folder_name = str_replace( '.zip', '', $filename );

			$res = $zip->open( $path );
			if ($res === TRUE) {
			  $zip->extractTo( truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/' . $folder_name . '/' );
			  $zip->close();
			}


			// create manifest
			$manifest = $this->_prepare_manifest();
			$content = fopen( truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/' . $folder_name . '/manifest.php', 'w') or die("Unable to open file!");
			fwrite( $content, $manifest );
			fclose( $content );
			wp_send_json_success();
		} else {
			wp_send_json_error();
		}


	}

	function _action_ajax_create_remote() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		$archives = $this->get_archives();

		if (
			empty($_POST['file'])
			||
			!isset($archives[ $filename = (string)$_POST['file'] ])
		) {
			wp_send_json_error(new WP_Error(
				'no_file', __('File not specified', 'fw')
			));
		}

		if ( $archives ) {
			$current_theme = wp_get_theme();
			$text_domain = $current_theme->get('TextDomain');
			$path = $archives[ $filename ][ 'path' ];
			$dstfile = truemag_UNYSON_BACKUP_DIR.'/remote-demo/'. $text_domain . ''.$filename;
			mkdir( dirname($dstfile), 0777, true );
			copy( $path, $dstfile);

			// create config file
			// $config = $this->_prepare_config( $filename, $dstfile );
			// $content = fopen( truemag_UNYSON_BACKUP_DIR.'/remote-demo/'. $text_domain . '/config.php', 'w') or die("Unable to open file!");
			// fwrite( $content, $config );
			// fclose( $content );
			// create script file

			if ( !file_exists( truemag_UNYSON_BACKUP_DIR.'/remote-demo/'. $text_domain . '/script.php' ) ) {
				$script = $this->_prepare_script();
				$content = fopen( truemag_UNYSON_BACKUP_DIR.'/remote-demo/'. $text_domain . '/script.php', 'w') or die("Unable to open file!");
				fwrite( $content, $script );
				fclose( $content );
			}
			wp_send_json_success();
		} else {
			wp_send_json_error();
		}
	}


	/**
	 * @internal
	 */
	public function _prepare_manifest() {
		$current_theme = wp_get_theme();

		$text_domain = $current_theme->get( 'TextDomain' );
		$theme_name = $current_theme->get( 'Name' );
		$theme_uri = $current_theme->get( 'ThemeURI' );
		$theme_version = $current_theme->get( 'Version' );
		$theme_author = $current_theme->get( 'Author' );
		$theme_author_uri = $current_theme->get( 'AuthorURI' );

		$html = "";
		$html .= "<?php if ( ! defined( 'FW' ) ) { die( 'Forbidden' ); }\n";
		$html .= "\$manifest = array();\n";
		$html .= "\$manifest['title'] = __( '".esc_html( $theme_name )."', '".esc_html( $text_domain )."' );\n";
		$html .= "\$manifest['screenshot'] = '".get_template_directory_uri()."/screenshot.png';\n";
		$html .= "\$manifest['preview_link'] = '';\n";
		$html .= "\$manifest['demo_link'] = '';\n";
		return $html;
	}

	function _prepare_config( $filename, $dstfile ){
		$html = "";
		$html .= "<?php\n";
		$html .= "\$cfg = array(\n";
			$html .=  "'files' => array(\n"; 
				$html .= "'".esc_html( $filename )."' => '".esc_html( $dstfile )."'\n";
			$html .=  "),\n";
		$html .=  ");\n";
		return $html;
	}

	function _prepare_script() {
		/**
		 * Send parts of file contents
		 */
		$html = "";
		$html .= "<?php\n";
		$html .= "\$megabyte = 1000 * 1000;\n";

		$html .= "{\n";
			$html .= "\$cfg = array();\n";
				$html .= "if (file_exists(\$config_path = dirname(__FILE__) .'/config.php')) {\n";
				$html .= "include \$config_path;\n";
			$html .= "}\n";

			$html .= "\$cfg = array_merge(array( 'files' => array(), 'size' => \$megabyte * 3 ), \$cfg);\n";

			$html .= "if (empty(\$cfg['files'])) {\n";
				$html .= "header('HTTP/1.1 500 Internal Server Error');\n";
				$html .= "exit;\n";
			$html .= "}\n";
		$html .= "}\n";

		$html .= "{\n";
			$html .= "{\n"; 
				$html .= "if (empty(\$_GET['id'])) {\n";
					$html .= "header('HTTP/1.1 400 Bad Request');\n";
					$html .= "exit;\n";
				$html .= "}\n";

				$html .= "\$id = \$_GET['id'];\n";

				$html .= "if (!isset(\$cfg['files'][ \$id ])) {\n";
					$html .= "header('HTTP/1.1 400 Bad Request');\n";
					$html .= "exit;\n";
				$html .= "}\n";
			$html .= "}\n";

			$html .= "{\n";
				$html .= "if (\n";
					$html .= "!isset(\$_GET['position'])\n";
					$html .= "||\n";
				    $html .= "!is_numeric(\$_GET['position'])\n";
				$html .= ") {\n";
					$html .= "header('HTTP/1.1 400 Bad Request');\n";
					$html .= "exit;\n";
				$html .= "}\n";

				$html .= "\$position = intval(\$_GET['position']);\n";

				$html .= "if ( \$position < 0 ) {\n";
					$html .= "header('HTTP/1.1 400 Bad Request');\n";
					$html .= "exit;\n";
				$html .= "}\n";
			$html .= "}\n";

			$html .= "if ( isset( \$_GET['size'] ) ) {\n";
				$html .= "\$size = \$_GET['size'];\n";

				$html .= "if (\n";
					$html .= "is_numeric( \$size )\n";
					$html .= "&&\n";
					$html .= "( \$size = intval( \$size) )\n";
					$html .= "&&\n";
					$html .= "\$size > 0\n";
					$html .= "&&\n";
					$html .= "\$size < \$megabyte * 10\n";
				$html .= ") {\n";
					$html .= "\$cfg['size'] = \$size;\n";
				$html .= "} else {\n";
					$html .= "header('HTTP/1.1 400 Bad Request');\n";
					$html .= "exit;\n";
				$html .= "}\n";
			$html .= "}\n";
		$html .= "}\n";

		$html .= "\$f = fopen( \$cfg['files'][ \$id ], 'r');\n";

		$html .= "if ( !\$f ) {\n";
			$html .= "header('HTTP/1.1 500 Internal Server Error');\n";
			$html .= "exit;\n";
		$html .= "}\n";

		$html .= "if ( -1 === fseek( \$f, \$position ) ) {\n";
			$html .= "header('HTTP/1.1 500 Internal Server Error');\n";
			$html .= "exit;\n";
		$html .= "}\n";

		$html .= "if (false === ( \$data = fread( \$f, \$cfg['size'] ) ) ) {\n";
			$html .= "header('HTTP/1.1 500 Internal Server Error');\n";
			$html .= "exit;\n";
		$html .= "}\n";

		$html .= "\$f = null;\n";

		$html .= "\$data_length = strlen( \$data );\n";

		$html .= "header('Content-Type: application/octet-stream');\n";
		$html .= "header('Content-Transfer-Encoding: binary');\n";
		$html .= "header('X-Position: '. ( \$data_length ? ( \$position + \$data_length ) : '-1'));\n";

		$html .= "if ( !\$position ) {\n";
			$html .= "if ( \$filesize = filesize( \$cfg['files'][ \$id ] ) ) {\n";
				$html .= "header( 'X-Filesize: ' . \$filesize );\n";
			$html .= "} else {\n";
				$html .= "header( 'HTTP/1.1 500 Internal Server Error' );\n";
				$html .= "exit;\n";
			$html .= "}\n";
		$html .= "}\n";

		$html .= "echo \$data;\n";


		return $html;
	}

	// end truemag custom

	

	/**
	 * @internal
	 */
	public function _action_ajax_cancel() {
		if (!current_user_can($this->get_capability())) {
			wp_send_json_error(new WP_Error('denied', 'Access Denied'));
		}

		if ($this->tasks()->do_cancel()) {
			wp_send_json_success();
		} else {
			wp_send_json_error();
		}
	}

	/**
	 * @internal
	 */
	public function _action_admin_menu() {
		call_user_func_array(
			is_multisite() && is_network_admin() ? 'add_menu_page' : 'add_management_page',
			array(
				__( 'Backup', 'fw' ),
				__( 'Backup', 'fw' ),
				$this->get_capability(),
				$this->get_page_slug(),
				array( $this, '_render_page' )
			)
		);
	}

	/**
	 * @param null|bool Get only full or content backups
	 * @return array Descending date sorting
	 */
	public function get_archives($full = null) {
		$archives = array();

		if ($this->server_requirements_not_met()) {
			return $archives;
		} elseif ($paths = glob($this->get_backups_dir() .'/*.zip')) {
			foreach ( $paths as $path ) {
				{
					$zip = new ZipArchive();

					if ( true === $zip->open( $path ) ) {
						$is_full = (bool) (
							$zip->locateName( 'f/themes/index.php' ) !== false
							||
							$zip->locateName( 'f/plugins/index.php' ) !== false
						);

						$zip->close();
					} else {
						trigger_error('Cannot open zip: '. $path, E_USER_WARNING);
						continue;
					}
				}

				if (
					!is_null($full)
					&&
					$full != $is_full
				) {
					continue;
				}

				$archives[ basename( $path ) ] = array(
					'path' => $path,
					'full' => $is_full,
					'time' => filemtime($path),
				);
			}
		}

		uasort($archives, array($this, '_archive_sort_callback'));

		return $archives;
	}

	public function _archive_sort_callback($a, $b) {
		if ($a['time'] == $b['time']) {
			return 0;
		} else {
			return ($a['time'] > $b['time']) ? -1 : 1;
		}
	}

	/**
	 * @internal
	 */
	public function _render_page() {
		echo '<div class="wrap">';

		if ($error_message = $this->server_requirements_not_met()) {
			echo "<div class=\"notice notice-error\"><p>{$error_message}</p></div>";
		} else {
			$this->render_view( 'page', array(
				'archives_html' => $this->render_view( 'archives', array(
					'archives' => $this->get_archives(),
					'is_busy'  => (bool) $this->tasks()->get_active_task_collection(),
				) ),
			), false );
		}

		echo '</div>';

		echo '<div id="fw-ext-backups-filesystem-form" style="display:none;">';
		FW_WP_Filesystem::request_access(ABSPATH);
		echo '</div>';
	}

	/**
	 * @return string
	 */
	public function get_tmp_dir() {
		return $this->get_backups_dir() . '/tmp';
	}

	/**
	 * All backups (zip) will go in this directory
	 * @return string
	 */
	public function get_backups_dir() {
		return $this->get_config( 'dirs.destination' );
	}

	/**
	 * {@inheritdoc}
	 */
	public function _get_link() {
		if (current_user_can($this->get_capability())) {
			return $this->get_page_url();
		} else {
			return null;
		}
	}

	/**
	 * @internal
	 */
	public function _get_test_ajax_action() {
		return self::$wp_ajax_action_test;
	}

	/**
	 * @internal
	 */
	public function _action_ajax_test() {
		wp_send_json_success();
	}

	public function get_download_link($archive_filename) {
		return add_query_arg(self::$download_GET_parameter, urlencode($archive_filename), $this->get_page_url());
	}

	// truemag custom
	public function get_download_demo_link($archive_filename) {
		return add_query_arg(self::$download_GET_demo_parameter, urlencode($archive_filename), $this->get_page_url());
	}

	public function _action_download() {
		if ( isset( $_GET[self::$download_GET_demo_parameter] ) ) {
			$demo_name = $_GET[self::$download_GET_demo_parameter];



			$current_theme = wp_get_theme();
			$text_domain = $current_theme->get('TextDomain');


			// create zip
			$download_zip = new ZipArchive;
			$folder_name = str_replace( '.zip', '', $demo_name );
			$rootPath = realpath( truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/' . $folder_name . '/' );

			$download_zip->open( truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/'. $demo_name , ZipArchive::CREATE | ZipArchive::OVERWRITE);
			$files = new RecursiveIteratorIterator(
				new RecursiveDirectoryIterator($rootPath),
				RecursiveIteratorIterator::LEAVES_ONLY
			);

			foreach ($files as $name => $file)
			{
				// Skip directories (they would be added automatically)
				if (!$file->isDir())
				{
					$filePath = $file->getRealPath();
					$relativePath = substr( $filePath, strlen($rootPath) + 1);

					// Add current file to archive
					$download_zip->addFile( $filePath, $relativePath);
				}
			}

			$download_zip->close();

			$downloadPath = realpath( truemag_UNYSON_BACKUP_DIR.'/theme-demo/'. $text_domain . '/' );
			$execPath = $downloadPath.'/'. $demo_name;
			do {
				if (!current_user_can($this->get_capability())) {
					$error = __('Access Denied', 'fw');
					break;
				}

				if ( $f = fopen( $execPath, 'r')) {
					// ok
				} else {
					$error = __('Failed to open file', 'fw');
					break;
				}

				header('Content-Type: application/zip, application/octet-stream');
				header('Content-Disposition: attachment; filename="'. esc_attr($demo_name) .'"');
				header('Content-length: '. filesize( $execPath ) );
				header('Cache-control: private');

				/**
				 * Some files can be huge, do not load entire file in php memory then output, it can cause memory limit error
				 * Read and output parts
				 */
				{
					$output_buffer_size = max(
						// https://github.com/ThemeFuse/Unyson/issues/2070#issuecomment-258427852
						(int)ini_get('output_buffering'),
						// default to this value in case ini_get() will return 0 (some server restrictions)
						// http://php.net/manual/en/outcontrol.configuration.php#ini.output-buffering
						4096
					);

					while (!feof($f)) {
						echo fread($f, $output_buffer_size);
						if (ob_get_level()) { ob_flush(); }
						flush();
					}
				}

				fclose($f);

				unlink( $execPath );


				exit;
			} while(false);

			wp_die($error, $error);

		} else {

			if (
				!isset($_GET[self::$download_GET_parameter])
				||
				!is_string($archive_filename = $_GET[self::$download_GET_parameter])
				||
				!$this->is_backups_page()
			) {
				return;
			}

			$error = __('Unknown error', 'fw');

			do {
				if (!current_user_can($this->get_capability())) {
					$error = __('Access Denied', 'fw');
					break;
				}

				$archives = $this->get_archives();

				if (!isset($archives[$archive_filename])) {
					$error = __('Archive not found', 'fw');
					break;
				}

				$archive = $archives[$archive_filename];

				if ($archive['full'] && !fw_ext_backups_current_user_can_full()) {
					$error = __('Access Denied', 'fw');
					break;
				}

				if ($f = fopen($archive['path'], 'r')) {
					// ok
				} else {
					$error = __('Failed to open file', 'fw');
					break;
				}

				header('Content-Type: application/zip, application/octet-stream');
				header('Content-Disposition: attachment; filename="'. esc_attr($archive_filename) .'"');
				header('Content-length: '. filesize($archive['path']));
				header('Cache-control: private');

				/**
				 * Some files can be huge, do not load entire file in php memory then output, it can cause memory limit error
				 * Read and output parts
				 */
				{
					$output_buffer_size = max(
						// https://github.com/ThemeFuse/Unyson/issues/2070#issuecomment-258427852
						(int)ini_get('output_buffering'),
						// default to this value in case ini_get() will return 0 (some server restrictions)
						// http://php.net/manual/en/outcontrol.configuration.php#ini.output-buffering
						4096
					);

					while (!feof($f)) {
						echo fread($f, $output_buffer_size);
						if (ob_get_level()) { ob_flush(); }
						flush();
					}
				}

				fclose($f);

				exit;
			} while(false);

			wp_die($error, $error);
		}
	}
}
