123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466 |
- <?php
- namespace Typemill\Models;
- use \URLify;
- class Folder
- {
- /*
- * scans content of a folder (without recursion)
- * vars: folder path as string
- * returns: one-dimensional array with names of folders and files
- */
- public static function scanFolderFlat($folderPath)
- {
- $folderItems = scandir($folderPath);
- $folderContent = array();
-
- foreach ($folderItems as $key => $item)
- {
- if (!in_array($item, array(".","..")))
- {
- $nameParts = self::getStringParts($item);
- $fileType = array_pop($nameParts);
-
- if($fileType == 'md' OR $fileType == 'txt' )
- {
- $folderContent[] = $item;
- }
- }
- }
- return $folderContent;
- }
-
-
- /*
- * scans content of a folder recursively
- * vars: folder path as string
- * returns: multi-dimensional array with names of folders and files
- */
- public static function scanFolder($folderPath, $draft = false)
- {
- $folderItems = scandir($folderPath);
- $folderContent = array();
- # if it is the live version and if it is a folder that is not published, then do not show the folder and its content.
- if(!$draft && !in_array('index.md', $folderItems)){ return false; }
- foreach ($folderItems as $key => $item)
- {
- if (!in_array($item, array(".","..")))
- {
- if (is_dir($folderPath . DIRECTORY_SEPARATOR . $item))
- {
- $subFolder = $item;
- $folderPublished = file_exists($folderPath . DIRECTORY_SEPARATOR . $item . DIRECTORY_SEPARATOR . 'index.md');
- # scan that folder only if it is a draft or if the folder is published (contains index.md)
- if($draft OR $folderPublished)
- {
- $folderContent[$subFolder] = self::scanFolder($folderPath . DIRECTORY_SEPARATOR . $subFolder, $draft);
- }
- }
- else
- {
- $nameParts = self::getStringParts($item);
- $fileType = array_pop($nameParts);
-
- if($fileType == 'md')
- {
- $folderContent[] = $item;
- }
-
- if($draft === true && $fileType == 'txt')
- {
- if(isset($last) && ($last == implode($nameParts)) )
- {
- array_pop($folderContent);
- $item = $item . 'md';
- }
- $folderContent[] = $item;
- }
-
- /* store the name of the last file */
- $last = implode($nameParts);
- }
- }
- }
- return $folderContent;
- }
-
- /*
- * Transforms array of folder item into an array of item-objects with additional information for each item
- * vars: multidimensional array with folder- and file-names
- * returns: array of objects. Each object contains information about an item (file or folder).
- */
- public static function getFolderContentDetails(array $folderContent, $baseUrl, $fullSlugWithFolder = NULL, $fullSlugWithoutFolder = NULL, $fullPath = NULL, $keyPath = NULL, $chapter = NULL)
- {
- $contentDetails = [];
- $iteration = 0;
- $chapternr = 1;
- foreach($folderContent as $key => $name)
- {
- $item = new \stdClass();
- if(is_array($name))
- {
- $nameParts = self::getStringParts($key);
-
- $fileType = '';
- if(in_array('index.md', $name))
- {
- $fileType = 'md';
- $status = 'published';
- }
- if(in_array('index.txt', $name))
- {
- $fileType = 'txt';
- $status = 'unpublished';
- }
- if(in_array('index.txtmd', $name))
- {
- $fileType = 'txt';
- $status = 'modified';
- }
- $item->originalName = $key;
- $item->elementType = 'folder';
- $item->status = $status;
- $item->fileType = $fileType;
- $item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
- $item->name = implode(" ",$nameParts);
- $item->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
- $item->slug = implode("-",$nameParts);
- $item->slug = URLify::filter(iconv(mb_detect_encoding($item->slug, mb_detect_order(), true), "UTF-8", $item->slug));
- $item->path = $fullPath . DIRECTORY_SEPARATOR . $key;
- $item->pathWithoutType = $fullPath . DIRECTORY_SEPARATOR . $key . DIRECTORY_SEPARATOR . 'index';
- $item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
- $item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
- $item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
- $item->key = $iteration;
- $item->keyPath = isset($keyPath) ? $keyPath . '.' . $iteration : $iteration;
- $item->keyPathArray = explode('.', $item->keyPath);
- $item->chapter = $chapter ? $chapter . '.' . $chapternr : $chapternr;
- $item->active = false;
- $item->activeParent = false;
- $item->folderContent = self::getFolderContentDetails($name, $baseUrl, $item->urlRel, $item->urlRelWoF, $item->path, $item->keyPath, $item->chapter);
- }
- else
- {
- # do not use files in base folder (only folders are allowed)
- # if(!isset($keyPath)) continue;
- # do not use index files
- if($name == 'index.md' || $name == 'index.txt' || $name == 'index.txtmd' ) continue;
- $nameParts = self::getStringParts($name);
- $fileType = array_pop($nameParts);
- $nameWithoutType = self::getNameWithoutType($name);
- if($fileType == 'md')
- {
- $status = 'published';
- }
- elseif($fileType == 'txt')
- {
- $status = 'unpublished';
- }
- else
- {
- $fileType = 'txt';
- $status = 'modified';
- }
- $item->originalName = $name;
- $item->elementType = 'file';
- $item->status = $status;
- $item->fileType = $fileType;
- $item->order = count($nameParts) > 1 ? array_shift($nameParts) : NULL;
- $item->name = implode(" ",$nameParts);
- $item->name = iconv(mb_detect_encoding($item->name, mb_detect_order(), true), "UTF-8", $item->name);
- $item->slug = implode("-",$nameParts);
- $item->slug = URLify::filter(iconv(mb_detect_encoding($item->slug, mb_detect_order(), true), "UTF-8", $item->slug));
- $item->path = $fullPath . DIRECTORY_SEPARATOR . $name;
- $item->pathWithoutType = $fullPath . DIRECTORY_SEPARATOR . $nameWithoutType;
- $item->key = $iteration;
- $item->keyPath = isset($keyPath) ? $keyPath . '.' . $iteration : $iteration;
- $item->keyPathArray = explode('.',$item->keyPath);
- $item->chapter = $chapter . '.' . $chapternr;
- $item->urlRelWoF = $fullSlugWithoutFolder . '/' . $item->slug;
- $item->urlRel = $fullSlugWithFolder . '/' . $item->slug;
- $item->urlAbs = $baseUrl . $fullSlugWithoutFolder . '/' . $item->slug;
- $item->active = false;
- $item->activeParent = false;
- }
- $iteration++;
- $chapternr++;
- $contentDetails[] = $item;
- }
- return $contentDetails;
- }
- public static function getItemForUrl($folderContentDetails, $url, $baseUrl, $result = NULL)
- {
- # if we are on the homepage
- if($url == '/' OR $url == $baseUrl)
- {
- # return a standard item-object
- $item = new \stdClass;
- $item->elementType = 'folder';
- $item->path = '';
- $item->urlRel = '/';
- $item->pathWithoutType = DIRECTORY_SEPARATOR . 'index';
- return $item;
- }
- foreach($folderContentDetails as $key => $item)
- {
- if($item->urlRel === $url)
- {
- # set item active, needed for move item in navigation
- $item->active = true;
- $result = $item;
- }
- elseif($item->elementType === "folder")
- {
- $result = self::getItemForUrl($item->folderContent, $url, $baseUrl, $result);
- }
- }
- return $result;
- }
- public static function getPagingForItem($content, $item)
- {
- $keyPos = count($item->keyPathArray)-1;
- $thisChapArray = $item->keyPathArray;
- $nextItemArray = $item->keyPathArray;
- $prevItemArray = $item->keyPathArray;
-
- $item->thisChapter = false;
- $item->prevItem = false;
- $item->nextItem = false;
-
-
- /************************
- * ADD THIS CHAPTER *
- ************************/
- if($keyPos > 0)
- {
- array_pop($thisChapArray);
- $item->thisChapter = self::getItemWithKeyPath($content, $thisChapArray);
- }
-
- /************************
- * ADD NEXT ITEM *
- ************************/
-
- if($item->elementType == 'folder')
- {
- /* get the first element in the folder */
- $item->nextItem = isset($item->folderContent[0]) ? clone($item->folderContent[0]) : false;
- }
-
- if(!$item->nextItem)
- {
- $nextItemArray[$keyPos]++;
- $item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
- }
-
- while(!$item->nextItem)
- {
- array_pop($nextItemArray);
- if(empty($nextItemArray)) break;
- $newKeyPos = count($nextItemArray)-1;
- $nextItemArray[$newKeyPos]++;
- $item->nextItem = self::getItemWithKeyPath($content, $nextItemArray);
- }
- /************************
- * ADD PREVIOUS ITEM *
- ************************/
-
- if($prevItemArray[$keyPos] > 0)
- {
- $prevItemArray[$keyPos]--;
- $item->prevItem = self::getItemWithKeyPath($content, $prevItemArray);
-
- if($item->prevItem && $item->prevItem->elementType == 'folder' && !empty($item->prevItem->folderContent))
- {
- /* get last item in folder */
- $item->prevItem = self::getLastItemOfFolder($item->prevItem);
- }
- }
- else
- {
- $item->prevItem = $item->thisChapter;
- }
-
- if($item->prevItem && $item->prevItem->elementType == 'folder'){ unset($item->prevItem->folderContent); }
- if($item->nextItem && $item->nextItem->elementType == 'folder'){ unset($item->nextItem->folderContent); }
- if($item->thisChapter){unset($item->thisChapter->folderContent); }
-
- return $item;
- }
- /*
- * Gets a copy of an item with a key
- * @param array $content with the full structure of the content as multidimensional array
- * @param array $searchArray with the key as a one-dimensional array like array(0,3,4)
- * @return array $item
- */
-
- public static function getItemWithKeyPath($content, array $searchArray)
- {
- $item = false;
- foreach($searchArray as $key => $itemKey)
- {
- $item = isset($content[$itemKey]) ? clone($content[$itemKey]) : false;
-
- unset($searchArray[$key]);
- if(!empty($searchArray) && $item)
- {
- return self::getItemWithKeyPath($item->folderContent, $searchArray);
- }
- }
- return $item;
- }
- # https://www.quora.com/Learning-PHP-Is-there-a-way-to-get-the-value-of-multi-dimensional-array-by-specifying-the-key-with-a-variable
- # NOT IN USE
- public static function getItemWithKeyPathNew($array, array $keys)
- {
- $item = $array;
-
- foreach ($keys as $key)
- {
- $item = isset($item[$key]->folderContent) ? $item[$key]->folderContent : $item[$key];
- }
-
- return $item;
- }
- /*
- * Extracts an item with a key https://stackoverflow.com/questions/52097092/php-delete-value-of-array-with-dynamic-key
- * @param array $content with the full structure of the content as multidimensional array
- * @param array $searchArray with the key as a one-dimensional array like array(0,3,4)
- * @return array $item
- * NOT IN USE ??
- */
-
- public static function extractItemWithKeyPath($structure, array $keys)
- {
- $result = &$structure;
- $last = array_pop($keys);
- foreach ($keys as $key) {
- if(isset($result[$key]->folderContent))
- {
- $result = &$result[$key]->folderContent;
- }
- else
- {
- $result = &$result[$key];
- }
- }
- $item = $result[$last];
- unset($result[$last]);
-
- return array('structure' => $structure, 'item' => $item);
- }
-
- /* get breadcrumb as copied array, set elements active in original and mark parent element in original */
- public static function getBreadcrumb($content, $searchArray, $i = NULL, $breadcrumb = NULL)
- {
- # if it is the first round, create an empty array
- if(!$i){ $i = 0; $breadcrumb = array();}
-
- while($i < count($searchArray))
- {
- $item = $content[$searchArray[$i]];
- if($i == count($searchArray)-1)
- {
- $item->active = true;
- }
- else
- {
- $item->activeParent = true;
- }
- /*
- $item->active = true;
- if($i == count($searchArray)-2)
- {
- $item->activeParent = true;
- }
- */
- $copy = clone($item);
- if($copy->elementType == 'folder')
- {
- unset($copy->folderContent);
- $content = $item->folderContent;
- }
- $breadcrumb[] = $copy;
-
- $i++;
- return self::getBreadcrumb($content, $searchArray, $i++, $breadcrumb);
- }
- return $breadcrumb;
- }
-
- public static function getParentItem($content, $searchArray, $iteration = NULL)
- {
- if(!$iteration){ $iteration = 0; }
- while($iteration < count($searchArray)-2)
- {
- $content = $content[$searchArray[$iteration]]->folderContent;
- $iteration++;
- return self::getParentItem($content, $searchArray, $iteration);
- }
- return $content[$searchArray[$iteration]];
- }
-
- private static function getLastItemOfFolder($folder)
- {
- $lastItem = end($folder->folderContent);
- if(is_object($lastItem) && $lastItem->elementType == 'folder' && !empty($lastItem->folderContent))
- {
- return self::getLastItemOfFolder($lastItem);
- }
- return $lastItem;
- }
-
- public static function getStringParts($name)
- {
- return preg_split('/[\-\.\_\=\+\?\!\*\#\(\)\/ ]/',$name);
- }
-
- public static function getFileType($fileName)
- {
- $parts = preg_split('/\./',$fileName);
- return end($parts);
- }
-
- public static function splitFileName($fileName)
- {
- $parts = preg_split('/\./',$fileName);
- return $parts;
- }
- public static function getNameWithoutType($fileName)
- {
- $parts = preg_split('/\./',$fileName);
- return $parts[0];
- }
- }
|