FDirectory   A
last analyzed

Complexity

Total Complexity 9

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 9
lcom 1
cbo 2
dl 0
loc 110
ccs 30
cts 30
cp 1
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A fmap() 0 6 1
A outer_fmap() 0 6 1
A fold() 0 10 2
A filter() 0 7 1
A fcontents() 0 8 2
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 class represents a directory with any content, not spefically files
14
 * or other directories.
15
 *
16
 * This is used to define and implement recursion. The directory structure
17
 * could be viewed as such (in Haskellish notation):
18
 *
19
 * There is a datatype for an abstract directory
20
 *
21
 *      data FDirectory a = FDirectory Metadata a
22
 *                        | FFile File
23
 *
24
 *
25
 * where Metadata means path and other filesystem metadata. The F stands
26
 * for Functor. A file could be described as
27
 *
28
 *      data File = File Metadata Content
29
 *
30
 * and a real filesystem then is
31
 *      newtype Directory = Directory { unfix :: FDirectory [Directory] }
32
 *
33
 * As a real implementation in PHP the metadata part is captured in the
34
 * FSObject class. As there are no type parameters in PHP, we define FDirectory
35
 * and Directory as separate classes, where unfix is implemented on FixedFDirectory.
36
 *
37
 * The implementation is also a little clunky, as this FDirectory mixes functionality
38
 * for FDirectory a and FDirectory [a]. That is FDirectory::outer_fmap is the 'real'
39
 * fmap from the functor FDirectory.
40
 */
41
class FDirectory extends FSObject
42
{
43
    /**
44
     * @var \Closure
45
     */
46
    protected $contents_lazy;
47
48
    /**
49
     * @var mixed
50
     */
51
    protected $contents = null;
52
53
    /**
54
     * As we need the metadata from FSObject, we need one of those. The
55
     * FDirectory a also has contents.
56
     *
57
     * Actually the second param should have a type like any, as we expect
58
     * a list from things of the same type.
59
     */
60 45
    public function __construct(FSObject $fs_object, \Closure $contents_lazy)
61
    {
62 45
        parent::__construct($fs_object->flightcontrol(), $fs_object->path());
63 45
        $this->contents_lazy = $contents_lazy;
64 45
    }
65
66
    /**
67
     * As this is as functor, we could map over it.
68
     *
69
     * Turns an FDirectory a to an FDirectory b by using the provided $trans
70
     * function.
71
     *
72
     * @param   \Closure    $trans   a -> b
73
     */
74 29
    public function fmap(\Closure $trans) : FDirectory
75
    {
76 29
        return $this->flightcontrol()->newFDirectory($this, function () use ($trans) {
77 29
            return array_map($trans, $this->fcontents());
78 29
        });
79
    }
80
81
    /**
82
     * We could also map the complete array to a new array, e.g. to
83
     * filter it, make it longer or shorter.
84
     *
85
     * @param   \Closure    $trans  [a] -> [b]
86
     * @throws  UnexpectedValueException    in case $trans returns no error
87
     */
88 30
    public function outer_fmap(\Closure $trans) : FDirectory
89
    {
90 30
        return $this->flightcontrol()->newFDirectory($this, function () use ($trans) {
91 30
            return $trans($this->fcontents());
92 30
        });
93
    }
94
95
    /**
96
     * Define the function to be iterated with and close this level
97
     * of iteration.
98
     *
99
     * @param   \Closure    $iteration  a -> File|Directory -> a
100
     */
101 18
    public function fold($start_value, $iteration) : FDirectory
102
    {
103 18
        return $this->outer_fmap(function ($contents) use ($start_value, $iteration) {
104 18
            $value = $start_value;
105 18
            foreach ($contents as $content) {
106 18
                $value = $iteration($value, $content);
107
            }
108 18
            return $value;
109 18
        });
110
    }
111
112
    /**
113
     * We could filter the FDirectory by a $predicate-
114
     *
115
     * @param   \Closure    $predicate  a -> bool
116
     */
117 21
    public function filter(\Closure $predicate) : FDirectory
118
    {
119
        return
120 21
        $this->outer_fmap(function ($fcontents) use ($predicate) {
121 21
            return array_filter($fcontents, $predicate);
122 21
        });
123
    }
124
125
    /**
126
     * The contents of this directory.
127
     *
128
     * It should really return type any[], as we do want to return an array
129
     * from things of the same type (but depend on the construction of this
130
     * object).
131
     *
132
     * @return  mixed[]     for an FDirectory a
133
     */
134 44
    public function fcontents() : array
135
    {
136 44
        if ($this->contents === null) {
137 44
            $cl = $this->contents_lazy;
138 44
            $this->contents = $cl();
139
        }
140 44
        return $this->contents;
141
    }
142
143
    /**
144
     * @inheritdoc
145
     */
146 20
    public function isFile() : bool
147
    {
148 20
        return false;
149
    }
150
}
151