[BUGFIX] Recycler doesn't show deleted pages for editors 92/45292/9
authorBernhard Kraft <kraftb@think-open.at>
Tue, 15 Dec 2015 13:57:55 +0000 (14:57 +0100)
committerAnja Leichsenring <aleichsenring@ab-softlab.de>
Sat, 16 Jan 2016 17:41:06 +0000 (18:41 +0100)
When using the recycler as normal user (non admin) it isn't possible
to restore any pages as the underlying BE API methods by default only
allow to check for access to non-deleted pages. This situation is
circumvented by disabling the "delete" flag in TCA while checking for
access to deleted pages.

Resolves: #70863
Releases: 7.6, master
Change-Id: Ibf6ff305a6dbcf3eaf99fdca89b7bf7c78677319
Reviewed-on: https://review.typo3.org/45292
Reviewed-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Tested-by: Morton Jonuschat <m.jonuschat@mojocode.de>
Reviewed-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
Tested-by: Anja Leichsenring <aleichsenring@ab-softlab.de>
15 files changed:
composer.json
composer.lock
typo3/sysext/core/Tests/FunctionalTestCase.php
typo3/sysext/recycler/Classes/Domain/Model/DeletedRecords.php
typo3/sysext/recycler/Classes/Utility/RecyclerUtility.php
typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_groups.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_users.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Fixtures/Database/pages.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/AbstractRecycleTestCase.php [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/Pages/AdminRecycleTest.php [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5_7.xml [new file with mode: 0644]
typo3/sysext/recycler/Tests/Functional/Recycle/Pages/UserRecycleTest.php [new file with mode: 0644]
typo3/sysext/recycler/composer.json

index aa0a8b8..dd1a50c 100644 (file)
                        "TYPO3\\CMS\\Saltedpasswords\\Tests\\": "typo3/sysext/saltedpasswords/Tests/",
                        "TYPO3\\CMS\\Scheduler\\Tests\\": "typo3/sysext/scheduler/Tests/",
                        "TYPO3\\CMS\\Sv\\Tests\\": "typo3/sysext/sv/Tests/",
-                       "TYPO3\\CMS\\Workspaces\\Tests\\": "typo3/sysext/workspaces/Tests/"
+                       "TYPO3\\CMS\\Workspaces\\Tests\\": "typo3/sysext/workspaces/Tests/",
+                       "TYPO3\\CMS\\Recycler\\Tests\\": "typo3/sysext/recycler/Tests/"
                },
                "classmap": ["typo3/sysext/extbase/Tests/Unit/Object/Container/Fixtures/"]
        },
index f1217ef..a86f49c 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
         "This file is @generated automatically"
     ],
-    "hash": "96968a49ae10d4bfdb2971d1edfc0596",
+    "hash": "f9a077a08a0ded52cb780607c99ca9b0",
     "content-hash": "ab559df12792276201af80afad0c2e24",
     "packages": [
         {
index 47c63b4..1c62924 100644 (file)
@@ -154,6 +154,13 @@ abstract class FunctionalTestCase extends BaseTestCase
     protected $additionalFoldersToCreate = array();
 
     /**
+     * The fixture which is used when initializing a backend user
+     *
+     * @var string
+     */
+    protected $backendUserFixture = 'typo3/sysext/core/Tests/Functional/Fixtures/be_users.xml';
+
+    /**
      * Private utility class used in setUp() and tearDown(). Do NOT use in test cases!
      *
      * @var \TYPO3\CMS\Core\Tests\FunctionalTestCaseBootstrapUtility
@@ -226,7 +233,7 @@ abstract class FunctionalTestCase extends BaseTestCase
      */
     protected function setUpBackendUserFromFixture($userUid)
     {
-        $this->importDataSet(ORIGINAL_ROOT . 'typo3/sysext/core/Tests/Functional/Fixtures/be_users.xml');
+        $this->importDataSet(ORIGINAL_ROOT . $this->backendUserFixture);
         $database = $this->getDatabaseConnection();
         $userRow = $database->exec_SELECTgetSingleRow('*', 'be_users', 'uid = ' . (int)$userUid);
 
index 396a0ed..a71099f 100644 (file)
@@ -256,11 +256,25 @@ class DeletedRecords
      */
     protected function checkRecordAccess($table, array $rows)
     {
+        if ($table === 'pages') {
+            // The "checkAccess" method validates access to the passed table/rows. When access to
+            // a page record gets validated it is necessary to disable the "delete" field temporarily
+            // for the recycler.
+            // Else it wouldn't be possible to perform the check as many methods of BackendUtility
+            // like "BEgetRootLine", etc. will only work on non-deleted records.
+            $deleteField = $GLOBALS['TCA'][$table]['ctrl']['delete'];
+            unset($GLOBALS['TCA'][$table]['ctrl']['delete']);
+        }
+
         foreach ($rows as $row) {
             if (RecyclerUtility::checkAccess($table, $row)) {
                 $this->setDeletedRows($table, $row);
             }
         }
+
+        if ($table === 'pages') {
+            $GLOBALS['TCA'][$table]['ctrl']['delete'] = $deleteField;
+        }
     }
 
     /**
@@ -335,7 +349,7 @@ class DeletedRecords
                     }
                     if (isset($cmd['pages'])) {
                         // reverse the page list to recover it from top to bottom
-                        $cmd['pages'] = array_reverse($cmd['pages'], TRUE);
+                        $cmd['pages'] = array_reverse($cmd['pages'], true);
                     }
                 }
                 $cmd[$table][$uid]['undelete'] = 1;
@@ -369,7 +383,8 @@ class DeletedRecords
      * @param array $pages
      * @return array
      */
-    protected function getDeletedParentPages($uid, &$pages = array()) {
+    protected function getDeletedParentPages($uid, &$pages = array())
+    {
         $db = $this->getDatabaseConnection();
         $res = $db->exec_SELECTquery('uid, pid', 'pages', 'uid=' . (int)$uid . ' AND ' . $GLOBALS['TCA']['pages']['ctrl']['delete'] . '=1');
         if ($res !== false && $db->sql_num_rows($res) > 0) {
index 34b1c9d..7020a3c 100644 (file)
@@ -47,8 +47,6 @@ class RecyclerUtility
         BackendUtility::fixVersioningPid($table, $calcPRec);
         if (is_array($calcPRec)) {
             if ($table === 'pages') {
-                // If pages:
-                // @todo: find a decent way for non-admins to get deleted pages respecting the permissions WITHOUT some isInWebMount stuff.
                 $calculatedPermissions = $backendUser->calcPerms($calcPRec);
                 $hasAccess = (bool)($calculatedPermissions & Permission::PAGE_EDIT);
             } else {
@@ -140,7 +138,8 @@ class RecyclerUtility
      * @param int $pid
      * @return bool
      */
-    public static function isParentPageDeleted($pid) {
+    public static function isParentPageDeleted($pid)
+    {
         if ((int)$pid === 0) {
             return false;
         }
@@ -160,7 +159,8 @@ class RecyclerUtility
      * @param string $table
      * @return int
      */
-    public static function getPidOfUid($uid, $table) {
+    public static function getPidOfUid($uid, $table)
+    {
         $db = static::getDatabaseConnection();
         $res = $db->exec_SELECTquery('pid', $table, 'uid=' . (int)$uid);
         if ($res !== false) {
diff --git a/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_groups.xml b/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_groups.xml
new file mode 100644 (file)
index 0000000..7394d26
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <be_groups>
+               <uid>1</uid>
+               <pid>0</pid>
+               <tstamp>1452959228</tstamp>
+               <title>editor-group</title>
+               <tables_modify>pages</tables_modify>
+               <crdate>1452959228</crdate>
+               <cruser_id>1</cruser_id>
+       </be_groups>
+</dataset>
diff --git a/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_users.xml b/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_users.xml
new file mode 100644 (file)
index 0000000..c386c25
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <be_users>
+               <uid>1</uid>
+               <pid>0</pid>
+               <tstamp>1366642540</tstamp>
+               <username>admin</username>
+               <password>$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1</password> <!-- password -->
+               <admin>1</admin>
+               <disable>0</disable>
+               <starttime>0</starttime>
+               <endtime>0</endtime>
+               <options>0</options>
+               <crdate>1366642540</crdate>
+               <cruser_id>0</cruser_id>
+               <workspace_perms>1</workspace_perms>
+               <disableIPlock>1</disableIPlock>
+               <deleted>0</deleted>
+               <TSconfig>NULL</TSconfig>
+               <lastlogin>1371033743</lastlogin>
+               <createdByAction>0</createdByAction>
+               <workspace_id>0</workspace_id>
+               <workspace_preview>1</workspace_preview>
+       </be_users>
+       <be_users>
+               <uid>2</uid>
+               <pid>0</pid>
+               <tstamp>1452944912</tstamp>
+               <username>editor</username>
+               <password>$1$tCrlLajZ$C0sikFQQ3SWaFAZ1Me0Z/1</password> <!-- password -->
+               <admin>0</admin>
+               <disable>0</disable>
+               <starttime>0</starttime>
+               <endtime>0</endtime>
+               <options>0</options>
+               <crdate>1452944912</crdate>
+               <cruser_id>1</cruser_id>
+               <workspace_perms>1</workspace_perms>
+               <disableIPlock>1</disableIPlock>
+               <deleted>0</deleted>
+               <TSconfig>NULL</TSconfig>
+               <lastlogin>1452944915</lastlogin>
+               <createdByAction>0</createdByAction>
+               <workspace_id>0</workspace_id>
+               <workspace_preview>1</workspace_preview>
+               <db_mountpoints>1</db_mountpoints>
+               <usergroup>1</usergroup>
+       </be_users>
+</dataset>
diff --git a/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/pages.xml b/typo3/sysext/recycler/Tests/Functional/Fixtures/Database/pages.xml
new file mode 100644 (file)
index 0000000..eca7b50
--- /dev/null
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <pages>
+               <uid>1</uid>
+               <pid>0</pid>
+               <title>Root</title>
+               <doktype>1</doktype>
+               <deleted>0</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>2</uid>
+               <pid>1</pid>
+               <title>Dummy 1-2</title>
+               <doktype>1</doktype>
+               <deleted>0</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>3</uid>
+               <pid>1</pid>
+               <title>Dummy 1-3 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>4</uid>
+               <pid>1</pid>
+               <title>Dummy 1-4 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>5</uid>
+               <pid>4</pid>
+               <title>Dummy 1-4-5 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>6</uid>
+               <pid>0</pid>
+               <title>Dummy 6 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>7</uid>
+               <pid>1</pid>
+               <title>Dummy 1-7 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>0</perms_everybody>
+       </pages>
+</dataset>
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/AbstractRecycleTestCase.php b/typo3/sysext/recycler/Tests/Functional/Recycle/AbstractRecycleTestCase.php
new file mode 100644 (file)
index 0000000..b197e0a
--- /dev/null
@@ -0,0 +1,122 @@
+<?php
+namespace TYPO3\CMS\Recycler\Tests\Functional\Recycle;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * Functional test for the Export
+ */
+abstract class AbstractRecycleTestCase extends \TYPO3\CMS\Core\Tests\FunctionalTestCase
+{
+    /**
+     * @var array
+     */
+    protected $coreExtensionsToLoad = array('recycler');
+
+    /**
+     * The fixture which is used when initializing a backend user
+     *
+     * @var string
+     */
+    protected $backendUserFixture = 'typo3/sysext/recycler/Tests/Functional/Fixtures/Database/be_users.xml';
+
+    /**
+     * Set up for set up the backend user, initialize the language object
+     * and creating the Export instance
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->importDataSet(__DIR__ . '/../Fixtures/Database/be_groups.xml');
+        \TYPO3\CMS\Core\Core\Bootstrap::getInstance()->initializeLanguageObject();
+    }
+
+    /**
+     * Retrieves deleted pages using the recycler domain model "deletedRecords" class.
+     *
+     * @param int $pageUid
+     * @param int $depth
+     * @return array Retrieved deleted records
+     */
+    protected function getDeletedPages($pageUid, $depth = 0)
+    {
+        /** @var $deletedRecords \TYPO3\CMS\Recycler\Domain\Model\DeletedRecords */
+        $deletedRecords = GeneralUtility::makeInstance(\TYPO3\CMS\Recycler\Domain\Model\DeletedRecords::class);
+        $deletedRecords->loadData($pageUid, 'pages', $depth);
+        return $deletedRecords->getDeletedRows();
+    }
+
+    /**
+     * Retrieves a deleted content elment using the recycler domain model "deletedRecords" class.
+     *
+     * @param int $contentUid
+     * @return array Retrieved deleted records
+     */
+    protected function getDeletedContent($contentUid)
+    {
+        /** @var $deletedRecords \TYPO3\CMS\Recycler\Domain\Model\DeletedRecords */
+        $deletedRecords = GeneralUtility::makeInstance(\TYPO3\CMS\Recycler\Domain\Model\DeletedRecords::class);
+        $deletedRecords->loadData($contentUid, 'tt_content', 0);
+        return $deletedRecords->getDeletedRows();
+    }
+
+    /**
+     * Loads a data set represented as XML and returns it as array.
+     *
+     * @param string $path Absolute path to the XML file containing the data set to load
+     * @return array The records loaded from the data set
+     * @throws \Exception
+     */
+    protected function loadDataSet($path)
+    {
+        if (!is_file($path)) {
+            throw new \Exception(
+                'Fixture file ' . $path . ' not found',
+                1376746261
+            );
+        }
+
+        $data = array();
+        $xml = simplexml_load_file($path);
+
+        /** @var $table \SimpleXMLElement */
+        foreach ($xml->children() as $table) {
+            $record = array();
+
+            /** @var $column \SimpleXMLElement */
+            foreach ($table->children() as $column) {
+                $columnName = $column->getName();
+                $columnValue = null;
+
+                if (isset($column['ref'])) {
+                    $columnValue = explode('#', $column['ref']);
+                } elseif (isset($column['is-NULL']) && ($column['is-NULL'] === 'yes')) {
+                    $columnValue = null;
+                } else {
+                    $columnValue = (string)$table->$columnName;
+                }
+
+                $record[$columnName] = $columnValue;
+            }
+
+            $tableName = $table->getName();
+            $data[$tableName][] = $record;
+        }
+        return $data;
+    }
+}
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/AdminRecycleTest.php b/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/AdminRecycleTest.php
new file mode 100644 (file)
index 0000000..9f4c8d5
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+namespace TYPO3\CMS\Recycler\Tests\Functional\Recycle\Pages;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Functional test for the Recycler
+ */
+class AdminRecycleTest extends \TYPO3\CMS\Recycler\Tests\Functional\Recycle\AbstractRecycleTestCase
+{
+    /**
+     * Directory which contains data sets for assertions
+     *
+     * @var string
+     */
+    protected $assertionDataSetDirectory = 'typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/';
+
+    /**
+     * Set up the test
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->importDataSet(__DIR__ . '/../../Fixtures/Database/pages.xml');
+        // Set up "admin" user
+        $this->setUpBackendUserFromFixture(1);
+    }
+
+    /**
+     * @test
+     */
+    public function retrieveDeletedPagesNoRecursion()
+    {
+        $deletedPages = $this->getDeletedPages(1, 0);
+        $assertData = $this->loadDataSet($this->assertionDataSetDirectory . 'deletedPage-3.xml');
+        $this->assertCount(1, $deletedPages);
+        $this->assertArrayHasKey('pages', $deletedPages);
+        $this->assertCount(3, $deletedPages['pages']);
+        $this->assertArraySubset($assertData, $deletedPages);
+    }
+
+    /**
+     * @test
+     */
+    public function retrieveDeletedPagesOneLevelRecursion()
+    {
+        $deletedPages = $this->getDeletedPages(1, 1);
+        $assertData = $this->loadDataSet($this->assertionDataSetDirectory . 'deletedPage-3_4_5_7.xml');
+        $this->assertCount(1, $deletedPages);
+        $this->assertArrayHasKey('pages', $deletedPages);
+        $this->assertCount(4, $deletedPages['pages']);
+        $this->assertArraySubset($assertData, $deletedPages);
+    }
+}
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3.xml b/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3.xml
new file mode 100644 (file)
index 0000000..083e2e1
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <pages>
+               <uid>3</uid>
+               <pid>1</pid>
+               <title>Dummy 1-3 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+</dataset>
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5.xml b/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5.xml
new file mode 100644 (file)
index 0000000..cc7bde3
--- /dev/null
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <pages>
+               <uid>3</uid>
+               <pid>1</pid>
+               <title>Dummy 1-3 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>4</uid>
+               <pid>1</pid>
+               <title>Dummy 1-4 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>5</uid>
+               <pid>4</pid>
+               <title>Dummy 1-4-5 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+</dataset>
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5_7.xml b/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/deletedPage-3_4_5_7.xml
new file mode 100644 (file)
index 0000000..4de2198
--- /dev/null
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<dataset>
+       <pages>
+               <uid>3</uid>
+               <pid>1</pid>
+               <title>Dummy 1-3 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>4</uid>
+               <pid>1</pid>
+               <title>Dummy 1-4 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+       <pages>
+               <uid>7</uid>
+               <pid>1</pid>
+               <title>Dummy 1-7 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>0</perms_everybody>
+       </pages>
+       <pages>
+               <uid>5</uid>
+               <pid>4</pid>
+               <title>Dummy 1-4-5 (deleted)</title>
+               <doktype>1</doktype>
+               <deleted>1</deleted>
+               <perms_everybody>15</perms_everybody>
+       </pages>
+</dataset>
+
diff --git a/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/UserRecycleTest.php b/typo3/sysext/recycler/Tests/Functional/Recycle/Pages/UserRecycleTest.php
new file mode 100644 (file)
index 0000000..1729c94
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+namespace TYPO3\CMS\Recycler\Tests\Functional\Recycle\Pages;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+/**
+ * Functional test for the Recycler
+ */
+class UserRecycleTest extends \TYPO3\CMS\Recycler\Tests\Functional\Recycle\AbstractRecycleTestCase
+{
+    /**
+     * Directory which contains data sets for assertions
+     *
+     * @var string
+     */
+    protected $assertionDataSetDirectory = 'typo3/sysext/recycler/Tests/Functional/Recycle/Pages/DataSet/Assertion/';
+
+    /**
+     * Set up the test
+     *
+     * @return void
+     */
+    protected function setUp()
+    {
+        parent::setUp();
+        $this->importDataSet(__DIR__ . '/../../Fixtures/Database/pages.xml');
+        // Set up "editor" user
+        $this->setUpBackendUserFromFixture(2);
+    }
+
+    /**
+     * @test
+     */
+    public function retrieveDeletedPagesNoRecursion()
+    {
+        $deletedPages = $this->getDeletedPages(1, 0);
+        $assertData = $this->loadDataSet($this->assertionDataSetDirectory . 'deletedPage-3.xml');
+        $this->assertCount(1, $deletedPages);
+        $this->assertArrayHasKey('pages', $deletedPages);
+        $this->assertCount(2, $deletedPages['pages']);
+        $this->assertArraySubset($assertData, $deletedPages);
+    }
+
+    /**
+     * @test
+     */
+    public function retrieveDeletedPagesOneLevelRecursion()
+    {
+        $deletedPages = $this->getDeletedPages(1, 1);
+        $assertData = $this->loadDataSet($this->assertionDataSetDirectory . 'deletedPage-3_4_5.xml');
+        $this->assertCount(1, $deletedPages);
+        $this->assertArrayHasKey('pages', $deletedPages);
+        $this->assertCount(3, $deletedPages['pages']);
+        $this->assertArraySubset($assertData, $deletedPages);
+    }
+
+    /**
+     * @test
+     */
+    public function canNotRetrieveDeletedPagesOutsideWebmount()
+    {
+        $deletedPages = $this->getDeletedPages(6, 0);
+        $this->assertCount(0, $deletedPages);
+    }
+
+    /**
+     * @test
+     */
+    public function canNotRetrieveDeletedWithNoAccess()
+    {
+        $deletedPages = $this->getDeletedPages(7, 0);
+        $this->assertCount(0, $deletedPages);
+    }
+}
index b0ff0d6..de9e07b 100644 (file)
                "psr-4": {
                        "TYPO3\\CMS\\Recycler\\": "Classes/"
                }
+       },
+       "autoload-dev": {
+               "psr-4": {
+                       "TYPO3\\CMS\\Recycler\\Tests\\": "Tests/"
+               }
        }
 }