1: <?php
2:
3: namespace Charcoal\Cms\Service\Loader;
4:
5: use Charcoal\Loader\CollectionLoader;
6: use Charcoal\Object\ObjectRoute;
7: use Exception;
8:
9: use \Charcoal\Translator\TranslatorAwareTrait;
10: 11: 12:
13: class SectionLoader extends AbstractLoader
14: {
15: 16: 17:
18: protected $sectionRoutes;
19:
20: 21: 22:
23: protected $baseSection;
24:
25: 26: 27: 28: 29:
30: protected static $snakeCache = [];
31:
32: 33: 34: 35:
36: public function fromId($id)
37: {
38: $proto = $this->modelFactory()->create($this->objType());
39:
40: return $proto->loadFrom('id', $id);
41: }
42:
43: 44: 45: 46:
47: public function fromSlug($slug)
48: {
49: $id = $this->resolveSectionId($slug);
50: return $this->fromId($id);
51: }
52:
53: 54: 55:
56: public function all()
57: {
58: $proto = $this->modelFactory()->get($this->objType());
59: $loader = $this->collectionLoader();
60: $loader->setModel($proto);
61: $loader->addFilter('active', true);
62: $loader->addOrder('position', 'asc');
63:
64: return $loader;
65: }
66:
67: 68: 69:
70: public function masters()
71: {
72: $loader = $this->all();
73: $operator = [];
74: if (!$this->baseSection()) {
75: $operator = [ 'operator' => 'IS NULL' ];
76: }
77: $loader->addFilter('master', $this->baseSection(), $operator);
78:
79: return $loader->load();
80: }
81:
82: 83: 84:
85: public function children()
86: {
87: $masters = $this->masters();
88:
89: $children = [];
90: $hasChildren = count($masters) > 0;
91:
92: while ($hasChildren) {
93: $ids = [];
94:
95: foreach ($masters as $master) {
96: $ids[] = $master->id();
97: }
98:
99: $masters = $this->all()
100: ->addFilter([
101: 'property' => 'master',
102: 'val' => $ids,
103: 'operator' => 'IN'
104: ])
105: ->load();
106:
107: $children = array_merge($children, $masters);
108: $hasChildren = count($masters) > 0;
109: }
110:
111: return $children;
112: }
113:
114: 115: 116: 117:
118: public function sectionRoutes()
119: {
120: if ($this->sectionRoutes) {
121: return $this->sectionRoutes;
122: }
123:
124: $proto = $this->modelFactory()->get(ObjectRoute::class);
125:
126: $sectionTypes = $this->sectionTypes();
127: if (!$sectionTypes) {
128: $sectionTypes = [
129: 'base' => $this->objType()
130: ];
131: }
132:
133: $loader = $this->collectionLoader();
134: $loader->setModel($proto);
135:
136: $filters = [];
137: foreach ($sectionTypes as $key => $val) {
138: $filters[] = 'route_obj_type = \''.$val.'\'';
139: }
140: $q = 'SELECT * FROM `'.$proto->source()->table().'`
141: WHERE active=1 AND ( '
142: . implode(' OR ', $filters) . ' )
143: ORDER BY creation_date ASC';
144:
145: $objectRoutes = $loader->loadFromQuery($q);
146:
147:
148:
149:
150:
151:
152:
153:
154:
155: $sections = [];
156: $routes = [];
157:
158: $lang = $this->translator()->getLocale();
159: foreach ($objectRoutes as $o) {
160: if ($o->lang() === $lang) {
161:
162: $sections[$o->routeObjId()] = $o->slug();
163: }
164:
165: $routes[$o->slug()] = $o->routeObjId();
166: }
167:
168: $this->sectionRoutes = [
169: 'sections' => $sections,
170: 'routes' => $routes
171: ];
172:
173: return $this->sectionRoutes;
174: }
175:
176: 177: 178: 179: 180:
181: public function resolveRoute($route)
182: {
183: $routes = $this->sectionRoutes();
184: $sId = $this->resolveSectionId($route);
185:
186: if (!isset($routes['sections'][$sId])) {
187: return '';
188: }
189:
190: return $routes['sections'][$sId];
191: }
192:
193: 194: 195: 196: 197:
198: public function resolveSectionId($route)
199: {
200: $routes = $this->sectionRoutes();
201:
202: if (!isset($routes['routes'][$route])) {
203: return '';
204: }
205:
206: $sId = $routes['routes'][$route];
207:
208: return $sId;
209: }
210:
211:
212:
213:
214:
215: 216: 217:
218: public function objType()
219: {
220: return $this->objType;
221: }
222:
223: 224: 225:
226: public function baseSection()
227: {
228: return $this->baseSection;
229: }
230:
231: 232: 233:
234: public function sectionTypes()
235: {
236: return $this->sectionTypes;
237: }
238:
239:
240:
241:
242:
243: 244: 245: 246:
247: public function setObjType($objType)
248: {
249: $this->objType = $objType;
250:
251: return $this;
252: }
253:
254: 255: 256: 257:
258: public function setBaseSection($baseSection)
259: {
260: $this->baseSection = $baseSection;
261:
262: return $this;
263: }
264:
265: 266: 267: 268:
269: public function setSectionTypes($sectionTypes)
270: {
271: $this->sectionTypes = $sectionTypes;
272:
273: return $this;
274: }
275:
276:
277:
278:
279:
280: 281: 282: 283: 284: 285: 286:
287: public static function snake($value, $delimiter = '-')
288: {
289: $key = $value;
290: if (isset(static::$snakeCache[$key][$delimiter])) {
291: return static::$snakeCache[$key][$delimiter];
292: }
293: if (!ctype_lower($value)) {
294: $value = preg_replace('/\s+/u', '', $value);
295: $value = mb_strtolower(preg_replace('/(.)(?=[A-Z])/u', '$1'.$delimiter, $value), 'UTF-8');
296: }
297: static::$snakeCache[$key][$delimiter] = $value;
298:
299: return $value;
300: }
301: }
302: