Overview

Namespaces

  • Charcoal
    • Admin
      • Widget
        • Cms
    • Cms
      • Config
      • Mixin
        • Traits
      • Route
      • Section
      • Service
        • Loader
        • Manager
      • ServiceProvider
      • Support
        • Helpers
        • Interfaces
        • Traits
    • Property

Classes

  • Charcoal\Admin\Widget\Cms\HierarchicalSectionTableWidget
  • Charcoal\Admin\Widget\Cms\SectionTableWidget
  • Charcoal\Cms\AbstractDocument
  • Charcoal\Cms\AbstractEvent
  • Charcoal\Cms\AbstractFaq
  • Charcoal\Cms\AbstractImage
  • Charcoal\Cms\AbstractNews
  • Charcoal\Cms\AbstractSection
  • Charcoal\Cms\AbstractText
  • Charcoal\Cms\AbstractVideo
  • Charcoal\Cms\Config
  • Charcoal\Cms\Config\CmsConfig
  • Charcoal\Cms\Config\EventConfig
  • Charcoal\Cms\Config\NewsConfig
  • Charcoal\Cms\Config\SectionConfig
  • Charcoal\Cms\Document
  • Charcoal\Cms\DocumentCategory
  • Charcoal\Cms\EmptySection
  • Charcoal\Cms\Event
  • Charcoal\Cms\EventCategory
  • Charcoal\Cms\ExternalSection
  • Charcoal\Cms\Faq
  • Charcoal\Cms\FaqCategory
  • Charcoal\Cms\Image
  • Charcoal\Cms\ImageCategory
  • Charcoal\Cms\News
  • Charcoal\Cms\NewsCategory
  • Charcoal\Cms\Route\EventRoute
  • Charcoal\Cms\Route\GenericRoute
  • Charcoal\Cms\Route\NewsRoute
  • Charcoal\Cms\Route\SectionRoute
  • Charcoal\Cms\Section
  • Charcoal\Cms\Section\BlocksSection
  • Charcoal\Cms\Section\ContentSection
  • Charcoal\Cms\Service\Loader\AbstractLoader
  • Charcoal\Cms\Service\Loader\EventLoader
  • Charcoal\Cms\Service\Loader\NewsLoader
  • Charcoal\Cms\Service\Loader\SectionLoader
  • Charcoal\Cms\Service\Manager\AbstractManager
  • Charcoal\Cms\Service\Manager\EventManager
  • Charcoal\Cms\Service\Manager\NewsManager
  • Charcoal\Cms\ServiceProvider\CmsServiceProvider
  • Charcoal\Cms\Support\Helpers\DateHelper
  • Charcoal\Cms\Tag
  • Charcoal\Cms\Text
  • Charcoal\Cms\TextCategory
  • Charcoal\Cms\Video
  • Charcoal\Cms\VideoCategory
  • Charcoal\Property\TemplateOptionsProperty
  • Charcoal\Property\TemplateProperty

Interfaces

  • Charcoal\Cms\DocumentInterface
  • Charcoal\Cms\EventInterface
  • Charcoal\Cms\FaqInterface
  • Charcoal\Cms\ImageInterface
  • Charcoal\Cms\MetatagInterface
  • Charcoal\Cms\Mixin\HasContentBlocksInterface
  • Charcoal\Cms\NewsInterface
  • Charcoal\Cms\SearchableInterface
  • Charcoal\Cms\SectionInterface
  • Charcoal\Cms\Support\Interfaces\EventManagerAwareInterface
  • Charcoal\Cms\Support\Interfaces\NewsManagerAwareInterface
  • Charcoal\Cms\Support\Interfaces\SectionLoaderAwareInterface
  • Charcoal\Cms\TemplateableInterface
  • Charcoal\Cms\TextInterface
  • Charcoal\Cms\VideoInterface

Traits

  • Charcoal\Admin\Widget\Cms\SectionTableTrait
  • Charcoal\Cms\MetatagTrait
  • Charcoal\Cms\Mixin\Traits\HasContentBlocksTrait
  • Charcoal\Cms\SearchableTrait
  • Charcoal\Cms\Support\Traits\DateHelperAwareTrait
  • Charcoal\Cms\Support\Traits\EventManagerAwareTrait
  • Charcoal\Cms\Support\Traits\NewsManagerAwareTrait
  • Charcoal\Cms\Support\Traits\SectionLoaderAwareTrait
  • Charcoal\Cms\TemplateableTrait
  • Overview
  • Namespace
  • Class
  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:  * Section Loader
 12:  */
 13: class SectionLoader extends AbstractLoader
 14: {
 15:     /**
 16:      * @var array $sectionRoutes The section's routes.
 17:      */
 18:     protected $sectionRoutes;
 19: 
 20:     /**
 21:      * @var integer $baseSection The id of the base section.
 22:      */
 23:     protected $baseSection;
 24: 
 25:     /**
 26:      * The cache of snake-cased words.
 27:      *
 28:      * @var array
 29:      */
 30:     protected static $snakeCache = [];
 31: 
 32:     /**
 33:      * @param integer $id The section's id.
 34:      * @return mixed
 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:      * @param string $slug The section's slug.
 45:      * @return mixed
 46:      */
 47:     public function fromSlug($slug)
 48:     {
 49:         $id = $this->resolveSectionId($slug);
 50:         return $this->fromId($id);
 51:     }
 52: 
 53:     /**
 54:      * @return CollectionLoader
 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:      * @return \ArrayAccess|\Traversable
 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:      * @return \ArrayAccess|\Traversable
 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:      * Pair routes slug to sections ID
116:      * @return array
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:         // $loader->addFilter('route_obj_type', $this->objType())
148:         //     // This is important. This is why it all works
149:         //     // Loading it from the first created to the last created
150:         //     // makes the following foreach override previous data.
151:         //     ->addOrder('creation_date', 'asc');
152: 
153:         // $objectRoutes = $loader->load();
154: 
155:         $sections = [];
156:         $routes = [];
157:         // The current language
158:         $lang = $this->translator()->getLocale();
159:         foreach ($objectRoutes as $o) {
160:             if ($o->lang() === $lang) {
161:                 // Will automatically override previous slug set
162:                 $sections[$o->routeObjId()] = $o->slug();
163:             }
164:             // Keep track of EVERY slug.
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:      * Resolve latest route from route slug.
178:      * @param  string $route The route to resolve.
179:      * @return string
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:      * Resolve section ID from route slug.
195:      * @param  string $route The route to resolve.
196:      * @return integer
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:     // GETTERS
213:     // ==========================================================================
214: 
215:     /**
216:      * @return object
217:      */
218:     public function objType()
219:     {
220:         return $this->objType;
221:     }
222: 
223:     /**
224:      * @return integer
225:      */
226:     public function baseSection()
227:     {
228:         return $this->baseSection;
229:     }
230: 
231:     /**
232:      * @return array
233:      */
234:     public function sectionTypes()
235:     {
236:         return $this->sectionTypes;
237:     }
238: 
239:     // ==========================================================================
240:     // SETTERS
241:     // ==========================================================================
242: 
243:     /**
244:      * @param object $objType The object type.
245:      * @return self
246:      */
247:     public function setObjType($objType)
248:     {
249:         $this->objType = $objType;
250: 
251:         return $this;
252:     }
253: 
254:     /**
255:      * @param integer $baseSection The base section id.
256:      * @return self
257:      */
258:     public function setBaseSection($baseSection)
259:     {
260:         $this->baseSection = $baseSection;
261: 
262:         return $this;
263:     }
264: 
265:     /**
266:      * @param array $sectionTypes Section types array | null.
267:      * @return self
268:      */
269:     public function setSectionTypes($sectionTypes)
270:     {
271:         $this->sectionTypes = $sectionTypes;
272: 
273:         return $this;
274:     }
275: 
276:     // ==========================================================================
277:     // UTILS
278:     // ==========================================================================
279: 
280:     /**
281:      * Convert a string to snake case.
282:      *
283:      * @param  string $value     The value to convert.
284:      * @param  string $delimiter The word delimiter.
285:      * @return string
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: 
API documentation generated by ApiGen