Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
45.71% covered (danger)
45.71%
16 / 35
20.00% covered (danger)
20.00%
1 / 5
CRAP
0.00% covered (danger)
0.00%
0 / 1
SwiftFileBackendList
47.06% covered (danger)
47.06%
16 / 34
20.00% covered (danger)
20.00%
1 / 5
28.95
0.00% covered (danger)
0.00%
0 / 1
 __construct
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
3.10
 key
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 next
0.00% covered (danger)
0.00%
0 / 12
0.00% covered (danger)
0.00%
0 / 1
20
 rewind
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
1
 valid
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 pageFromList
n/a
0 / 0
n/a
0 / 0
0
1<?php
2/**
3 * OpenStack Swift based file backend.
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * http://www.gnu.org/copyleft/gpl.html
19 *
20 * @file
21 * @ingroup FileBackend
22 * @author Russ Nelson
23 */
24
25namespace Wikimedia\FileBackend\FileIteration;
26
27use Iterator;
28use Traversable;
29use Wikimedia\FileBackend\SwiftFileBackend;
30
31/**
32 * SwiftFileBackend helper class to page through listings.
33 * Swift also has a listing limit of 10,000 objects for performance.
34 * Do not use this class from places outside SwiftFileBackend.
35 *
36 * @ingroup FileBackend
37 */
38abstract class SwiftFileBackendList implements Iterator {
39    /** @var string[]|array[] Current page of entries; path list or (path,stat map) list */
40    protected $iterableBuffer = [];
41
42    /** @var string|null Continuation marker; the next page starts *after* this path */
43    protected $continueAfter = null;
44
45    /** @var int */
46    protected $pos = 0;
47
48    /** @var array */
49    protected $params = [];
50
51    /** @var SwiftFileBackend */
52    protected $backend;
53
54    /** @var string Container name */
55    protected $container;
56
57    /** @var string Storage directory */
58    protected $dir;
59
60    /** @var int */
61    protected $suffixStart;
62
63    private const PAGE_SIZE = 9000; // file listing buffer size
64
65    /**
66     * @param SwiftFileBackend $backend
67     * @param string $fullCont Resolved container name
68     * @param string $dir Resolved directory relative to container
69     * @param array $params
70     * @note This defers I/O by not buffering the first page (useful for AppendIterator use)
71     * @note Do not call current()/valid() without calling rewind() first
72     */
73    public function __construct( SwiftFileBackend $backend, $fullCont, $dir, array $params ) {
74        $this->backend = $backend;
75        $this->container = $fullCont;
76        $this->dir = $dir;
77        if ( substr( $this->dir, -1 ) === '/' ) {
78            $this->dir = substr( $this->dir, 0, -1 ); // remove trailing slash
79        }
80        if ( $this->dir == '' ) { // whole container
81            $this->suffixStart = 0;
82        } else { // dir within container
83            $this->suffixStart = strlen( $this->dir ) + 1; // size of "path/to/dir/"
84        }
85        $this->params = $params;
86    }
87
88    /**
89     * @see Iterator::key()
90     * @return int
91     */
92    public function key(): int {
93        return $this->pos;
94    }
95
96    /**
97     * @inheritDoc
98     */
99    public function next(): void {
100        ++$this->pos;
101        if ( $this->iterableBuffer === null ) {
102            // Last page of entries failed to load
103            return;
104        }
105        // Advance to the next entry in the page
106        next( $this->iterableBuffer );
107        // Check if there are no entries left in this page and
108        // advance to the next page if this page was not empty.
109        if ( !$this->valid() && count( $this->iterableBuffer ) ) {
110            $this->iterableBuffer = $this->pageFromList(
111                $this->container,
112                $this->dir,
113                $this->continueAfter,
114                self::PAGE_SIZE,
115                $this->params
116            );
117        }
118    }
119
120    /**
121     * @inheritDoc
122     */
123    public function rewind(): void {
124        $this->pos = 0;
125        $this->continueAfter = null;
126        $this->iterableBuffer = $this->pageFromList(
127            $this->container,
128            $this->dir,
129            // @phan-suppress-next-line PhanTypeMismatchArgumentPropertyReferenceReal
130            $this->continueAfter,
131            self::PAGE_SIZE,
132            $this->params
133        );
134    }
135
136    /**
137     * @see Iterator::valid()
138     * @return bool
139     */
140    public function valid(): bool {
141        if ( $this->iterableBuffer === null ) {
142            // Last page of entries failed to load
143            return false;
144        }
145        // Note that entries (paths/tuples) are never boolean
146        return ( current( $this->iterableBuffer ) !== false );
147    }
148
149    /**
150     * Get the next page of entries
151     *
152     * @param string $container Resolved container name
153     * @param string $dir Resolved path relative to container
154     * @param string &$after @phan-output-reference Continuation marker
155     * @param int $limit
156     * @param array $params
157     * @return Traversable|array
158     */
159    abstract protected function pageFromList( $container, $dir, &$after, $limit, array $params );
160}
161
162/** @deprecated class alias since 1.43 */
163class_alias( SwiftFileBackendList::class, 'SwiftFileBackendList' );