Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
<?php
namespace Drupal\subrequests\Blueprint;
use Symfony\Component\HttpFoundation\Request;
/**
* Contains the hierarchical information of the requests.
*/
class RequestTree {
const SUBREQUEST_TREE = '_subrequests_tree_object';
const SUBREQUEST_ID = '_subrequests_content_id';
const SUBREQUEST_DONE = '_subrequests_is_done';
/**
* @var \Symfony\Component\HttpFoundation\Request[]
*/
protected $requests;
/**
* If this tree sprouts from another requests, save the request id here.
* @var string
*/
protected $parentId;
/**
* RequestTree constructor.
*
* @param \Symfony\Component\HttpFoundation\Request[] $requests
* @param string $parent_id
*/
public function __construct(array $requests, $parent_id = NULL) {
$this->requests = $requests;
$this->parentId = $parent_id;
}
/**
* Gets a flat list of the initialized requests for the current level.
*
* All requests returned by this method can run in parallel. If a request has
* children requests depending on it (sequential) the parent request will
* contain a RequestTree itself.
*
* @return \Symfony\Component\HttpFoundation\Request[]
* The list of requests.
*/
public function getRequests() {
return $this->requests;
}
/**
* Is this tree the base one?
*
* @return bool
* TRUE if the tree is for the master request.
*/
public function isRoot() {
return !$this->getParentId();
}
/**
* Get the parent ID of the request this tree belongs to.
*
* @return string
*/
public function getParentId() {
return $this->parentId;
}
/**
* Find all the sub-trees in this tree.
*
* @return static[]
* An array of trees.
*/
public function getSubTrees() {
$trees = array_map(function (Request $request) {
return $request->attributes->get(static::SUBREQUEST_TREE);
}, $this->getRequests());
return array_filter($trees);
}
/**
* Find a request in a tree based on the request ID.
*
* @param string $request_id
* The unique ID of a request in the blueprint to find in this tree.
*
* @return \Symfony\Component\HttpFoundation\Request|NULL $request
* The request if found. NULL if not found.
*/
public function getDescendant($request_id) {
// Search this level's requests.
$found = array_filter($this->getRequests(), function (Request $request) use ($request_id) {
return $request->attributes->get(static::SUBREQUEST_ID) == $request_id;
});
if (count($found)) {
return reset($found);
}
// If the request is not in this level, then traverse the children's trees.
$found = array_filter($this->getRequests(), function (Request $request) use ($request_id) {
/** @var static $sub_tree */
if (!$sub_tree = $request->attributes->get(static::SUBREQUEST_TREE)) {
return FALSE;
}
return $sub_tree->getDescendant($request_id);
});
if (count($found)) {
return reset($found);
}
return NULL;
}
/**
* Is the request tree done?
*
* @return bool
* TRUE if all the requests in the tree and it's descendants are done.
*/
public function isDone() {
// The tree is done if all of the requests and their children are done.
return array_reduce($this->getRequests(), function ($is_done, Request $request) {
return $is_done && static::isRequestDone($request);
}, TRUE);
}
/**
* Check if a request and all its possible children are done.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
*
* @return bool
* TRUE if is done. FALSE otherwise.
*/
protected static function isRequestDone(Request $request) {
// If one request is not done, the whole tree is not done.
if (!$request->attributes->get(static::SUBREQUEST_DONE)) {
return FALSE;
}
// If the request has children, then make sure those are done too.
/** @var static $sub_tree */
if ($sub_tree = $request->attributes->get(static::SUBREQUEST_TREE)) {
if (!$sub_tree->isDone()) {
return FALSE;
}
}
return TRUE;
}
}