Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
RevisionViewQuery
0.00% covered (danger)
0.00%
0 / 58
0.00% covered (danger)
0.00%
0 / 5
462
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
2
 createRevision
n/a
0 / 0
n/a
0 / 0
0
 getSingleViewResult
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
12
 getDiffViewResult
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
72
 getUndoDiffResult
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
56
 isComparable
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3namespace Flow\Formatter;
4
5use Flow\Data\ManagerGroup;
6use Flow\Exception\InvalidInputException;
7use Flow\Exception\InvalidParameterException;
8use Flow\Exception\PermissionException;
9use Flow\Model\AbstractRevision;
10use Flow\Model\UUID;
11use Flow\Repository\TreeRepository;
12use Flow\RevisionActionPermissions;
13
14abstract class RevisionViewQuery extends AbstractQuery {
15
16    /**
17     * @var RevisionActionPermissions
18     */
19    protected $permissions;
20
21    /**
22     * @param ManagerGroup $storage
23     * @param TreeRepository $treeRepository
24     * @param RevisionActionPermissions $permissions
25     */
26    public function __construct(
27        ManagerGroup $storage,
28        TreeRepository $treeRepository,
29        RevisionActionPermissions $permissions
30    ) {
31        parent::__construct( $storage, $treeRepository );
32        $this->permissions = $permissions;
33    }
34
35    /**
36     * Create a revision based on revisionId
37     * @param UUID|string $revId
38     * @return AbstractRevision
39     */
40    abstract protected function createRevision( $revId );
41
42    /**
43     * Get the data for rendering single revision view
44     * @param string $revId
45     * @return FormatterRow|null
46     * @throws InvalidInputException
47     */
48    public function getSingleViewResult( $revId ) {
49        if ( !$revId ) {
50            throw new InvalidParameterException( 'Missing revision' );
51        }
52        $rev = $this->createRevision( $revId );
53        if ( !$rev ) {
54            throw new InvalidInputException( 'Could not find revision: ' . $revId, 'missing-revision' );
55        }
56        $this->loadMetadataBatch( [ $rev ] );
57        return $this->buildResult( $rev, null );
58    }
59
60    /**
61     * Get the data for rendering revisions diff view
62     * @param UUID $curId
63     * @param UUID|null $prevId
64     * @return FormatterRow[]
65     * @throws InvalidInputException
66     * @throws PermissionException
67     */
68    public function getDiffViewResult( UUID $curId, ?UUID $prevId = null ) {
69        $cur = $this->createRevision( $curId );
70        if ( !$cur ) {
71            throw new InvalidInputException( 'Could not find revision: ' . $curId, 'missing-revision' );
72        }
73        if ( !$prevId ) {
74            $prevId = $cur->getPrevRevisionId();
75        }
76        // @phan-suppress-next-line PhanTypeMismatchArgumentNullable
77        $prev = $this->createRevision( $prevId );
78        if ( !$prev ) {
79            throw new InvalidInputException(
80                'Could not find revision to compare against: ' . $curId->getAlphadecimal(),
81                'missing-revision'
82            );
83        }
84        if ( !$this->isComparable( $cur, $prev ) ) {
85            throw new InvalidInputException( 'Attempt to compare revisions of different types', 'revision-comparison' );
86        }
87
88        // Re-position old and new revisions if necessary
89        if (
90            $cur->getRevisionId()->getTimestamp() >
91            $prev->getRevisionId()->getTimestamp()
92        ) {
93            $oldRev = $prev;
94            $newRev = $cur;
95        } else {
96            $oldRev = $cur;
97            $newRev = $prev;
98        }
99
100        if (
101            !$this->permissions->isAllowed( $oldRev, 'view' ) ||
102            !$this->permissions->isAllowed( $newRev, 'view' )
103        ) {
104            throw new PermissionException( 'Insufficient permission to compare revisions', 'insufficient-permission' );
105        }
106
107        $this->loadMetadataBatch( [ $oldRev, $newRev ] );
108
109        return [
110            $this->buildResult( $newRev, null ),
111            $this->buildResult( $oldRev, null ),
112        ];
113    }
114
115    public function getUndoDiffResult( $startUndoId, $endUndoId ) {
116        $start = $this->createRevision( $startUndoId );
117        if ( !$start ) {
118            throw new InvalidInputException( 'Could not find revision: ' . $startUndoId, 'missing-revision' );
119        }
120        $end = $this->createRevision( $endUndoId );
121        if ( !$end ) {
122            throw new InvalidInputException( 'Could not find revision: ' . $endUndoId, 'missing-revision' );
123        }
124
125        // the two revision must have the same revision type id
126        if ( !$start->getCollectionId()->equals( $end->getCollectionId() ) ) {
127            throw new InvalidInputException( 'start and end are not from the same set' );
128        }
129
130        $current = $start->getCollection()->getLastRevision();
131
132        if (
133            !$this->permissions->isAllowed( $start, 'view' ) ||
134            !$this->permissions->isAllowed( $end, 'view' ) ||
135            !$this->permissions->isAllowed( $current, 'view' )
136        ) {
137            throw new PermissionException( 'Insufficient permission to undo revisions', 'insufficient-permission' );
138        }
139
140        $this->loadMetadataBatch( [ $start, $end, $current ] );
141
142        return [
143            $this->buildResult( $start, null ),
144            $this->buildResult( $end, null ),
145            $this->buildResult( $current, null ),
146        ];
147    }
148
149    public function isComparable( AbstractRevision $cur, AbstractRevision $prev ) {
150        if ( $cur->getRevisionType() == $prev->getRevisionType() ) {
151            return $cur->getCollectionId()->equals( $prev->getCollectionId() );
152        } else {
153            return false;
154        }
155    }
156}