core-bundle/src/Resources/contao/drivers/DC_Table.php
public function undo()
	{
		$objRecords = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")
									 ->limit(1)
									 ->execute($this->intId);

		// Check whether there is a record
		if ($objRecords->numRows < 1)
		{
			$this->redirect($this->getReferer());
		}

		$error = false;
		$query = $objRecords->query;
		$data = StringUtil::deserialize($objRecords->data);

		if (!\is_array($data))
		{
			$this->redirect($this->getReferer());
		}

		$arrFields = array();

		// Restore the data
		foreach ($data as $table=>$fields)
		{
			$this->loadDataContainer($table);

			// Get the currently available fields
			if (!isset($arrFields[$table]))
			{
				$arrFields[$table] = array_flip($this->Database->getFieldNames($table));
			}

			foreach ($fields as $row)
			{
				// Unset fields that no longer exist in the database
				$row = array_intersect_key($row, $arrFields[$table]);

				// Re-insert the data
				$objInsertStmt = $this->Database->prepare("INSERT INTO " . $table . " %s")
												->set($row)
												->execute();

				// Do not delete record from tl_undo if there is an error
				if ($objInsertStmt->affectedRows < 1)
				{
					$error = true;
				}

				// Trigger the undo_callback
				if (\is_array($GLOBALS['TL_DCA'][$table]['config']['onundo_callback']))
				{
					foreach ($GLOBALS['TL_DCA'][$table]['config']['onundo_callback'] as $callback)
					{
						if (\is_array($callback))
						{
							$this->import($callback[0]);
							$this->{$callback[0]}->{$callback[1]}($table, $row, $this);
						}
						elseif (\is_callable($callback))
						{
							$callback($table, $row, $this);
						}
					}
				}
			}
		}

		// Add log entry and delete record from tl_undo if there was no error
		if (!$error)
		{
			$this->log('Undone '. $query, __METHOD__, TL_GENERAL);

			$this->Database->prepare("DELETE FROM " . $this->strTable . " WHERE id=?")
						   ->limit(1)
						   ->execute($this->intId);
		}

		$this->redirect($this->getReferer());
	}
public function undo()
	{
		$objRecords = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")
									 ->limit(1)
									 ->execute($this->intId);

		// Check whether there is a record
		if ($objRecords->numRows < 1)
		{
			$this->redirect($this->getReferer());
		}

		$error = false;
		$query = $objRecords->query;
		$data = StringUtil::deserialize($objRecords->data);

		if (!\is_array($data))
		{
			$this->redirect($this->getReferer());
		}

		$arrFields = array();

		// Restore the data
		foreach ($data as $table=>$fields)
		{
			$this->loadDataContainer($table);

			// Get the currently available fields
			if (!isset($arrFields[$table]))
			{
				$arrFields[$table] = array_flip($this->Database->getFieldNames($table));
			}

			foreach ($fields as $row)
			{
				// Unset fields that no longer exist in the database
				$row = array_intersect_key($row, $arrFields[$table]);

				// Re-insert the data
				$objInsertStmt = $this->Database->prepare("INSERT INTO " . $table . " %s")
												->set($row)
												->execute();

				// Do not delete record from tl_undo if there is an error
				if ($objInsertStmt->affectedRows < 1)
				{
					$error = true;
				}

				// Trigger the undo_callback
				if (\is_array($GLOBALS['TL_DCA'][$table]['config']['onundo_callback']))
				{
					foreach ($GLOBALS['TL_DCA'][$table]['config']['onundo_callback'] as $callback)
					{
						if (\is_array($callback))
						{
							$this->import($callback[0]);
							$this->{$callback[0]}->{$callback[1]}($table, $row, $this);
						}
						elseif (\is_callable($callback))
						{
							$callback($table, $row, $this);
						}
					}
				}
			}
		}

		// Add log entry and delete record from tl_undo if there was no error
		if (!$error)
		{
			$this->log('Undone '. $query, __METHOD__, TL_GENERAL);

			$this->Database->prepare("DELETE FROM " . $this->strTable . " WHERE id=?")
						   ->limit(1)
						   ->execute($this->intId);
		}

		$this->redirect($this->getReferer());
	}
Restore one or more deleted records