Recursor   A
last analyzed

Complexity

Total Complexity 12

Size/Duplication

Total Lines 126
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Test Coverage

Coverage 92.5%

Importance

Changes 0
Metric Value
wmc 12
lcom 1
cbo 4
dl 0
loc 126
ccs 37
cts 40
cp 0.925
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A filter() 0 15 2
A cata() 0 10 2
A with() 0 4 1
A foldFiles() 0 7 2
A allFiles() 0 15 3
A isFile() 0 4 1
1
<?php
2
/******************************************************************************
3
 * An iterator interface over the Leagues flysystem.
4
 * Copyright (c) 2021, 2015 Richard Klees <[email protected]>
5
 *
6
 * This software is licensed under GPLv3. You should have received
7
 * a copy of the along with the code.
8
 */
9
10
namespace Lechimp\Flightcontrol;
11
12
/**
13
* This object can perform a recursion on the files in a directory.
14
* I don't know if the name really fits.
15
*/
16
class Recursor extends FSObject
17
{
18 1
    use FilterTrait;
19
20
    /**
21
     * @var FixedFDirectory
22
     */
23
    protected $directory;
24
25 16
    public function __construct(FixedFDirectory $directory)
26
    {
27 16
        parent::__construct($directory->flightcontrol(), $directory->path());
28 16
        $this->directory = $directory;
29 16
    }
30
31
    /**
32
     * Get a recursor that folds all files in this recursor that match the
33
     * provided predicate and the objects below that match the predicate as
34
     * well.
35
     *
36
     * Won't recurse over directories that do not match the predicate!
37
     *
38
     * @param  \Closure             $predicate  (FSObject -> Bool)
39
     */
40 8
    public function filter(\Closure $predicate) : Recursor
41
    {
42 8
        $filter = array();
43 8
        $filter[0] = function (FixedFDirectory $obj) use ($predicate, &$filter) {
44
            return $obj
45 8
                ->filter($predicate)
46 8
                ->map(function (FSObject $obj) use ($predicate, &$filter) {
47 8
                    if ($obj->isFile()) {
48 6
                        return $obj;
49
                    }
50 8
                    return $filter[0]($obj);
51 8
                });
52
        };
53 8
        return new Recursor($filter[0]($this->directory));
54
    }
55
56
    /**
57
     * We could also use the catamorphism on this to do recursion, as we
58
     * have an unfix and an underlying fmap from the FDirectory.
59
     *
60
     * Supply a function $trans from File|FDirectory a to a that flattens
61
     * (folds) a directory. Will start the directories where only files are
62
     * included, folds them and then proceeds upwards.
63
     *
64
     * The return type should be 'a' (from the function $trans) instead
65
     * of mixed, but we can't express that fact correctly in the docstring
66
     * typing.
67
     *
68
     * @param   \Closure    $trans      File|FDirectory a -> a
69
     * @return  mixed
70
     */
71 16
    public function cata(\Closure $trans)
72
    {
73 16
        return $trans($this->directory->unfix()->fmap(function (FSObject $obj) use ($trans) {
74 16
            if ($obj->isFile()) {
75 14
                return $trans($obj);
76
            }
77 16
            assert($obj instanceof FixedFDirectory);
78 16
            return $obj->cata($trans);
79 16
        }));
80
    }
81
82
    /**
83
     * Sugar for cata.
84
     *
85
     * @param   \Closure    $trans      File|FDirectory a -> a
86
     * @return  mixed
87
     */
88 4
    public function with(\Closure $trans)
89
    {
90 4
        return $this->cata($trans);
91
    }
92
93
    /**
94
     * Fold over all files in this directory and subjacent directories.
95
     *
96
     * Start with an initial value of some type and a function from that type
97
     * and File to a new value of the type. Will successively feed all files
98
     * and the resulting values to that function.
99
     *
100
     * @param   mixed       $start_value
101
     * @param   \Closure    $fold_with      a -> File -> a
102
     * @return Recursor|array
103
     */
104 6
    public function foldFiles($start_value, \Closure $fold_with)
105
    {
106 6
        foreach ($this->allFiles() as $file) {
107 6
            $start_value = $fold_with($start_value, $file);
108
        }
109 6
        return $start_value;
110
    }
111
112
    /**
113
     * Get a list of all files in the directory and subjacent directories.
114
     *
115
     * @return File[]
116
     */
117 10
    public function allFiles() : array
118
    {
119 10
        return $this->cata(function (FSObject $obj) {
120 10
            if ($obj->isFile()) {
121 10
                return array($obj);
122
            }
123
124 10
            assert($obj instanceof FDirectory);
125 10
            $fcontents = $obj->fcontents();
126 10
            if (empty($fcontents)) {
127
                return $fcontents;
128
            }
129 10
            return call_user_func_array("array_merge", $fcontents);
130 10
        });
131
    }
132
     
133
134
    /**
135
     * @inheritdoc
136
     */
137
    public function isFile() : bool
138
    {
139
        return false;
140
    }
141
}
142