Skip to content

Commit

Permalink
feat: config to define a default sort method (#1864)
Browse files Browse the repository at this point in the history
  • Loading branch information
ArnaudLigny authored Dec 20, 2023
1 parent 80190b8 commit cb72c12
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 47 deletions.
6 changes: 6 additions & 0 deletions config/default.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,12 @@
'dir' => 'pages', // pages files directory (`pages` by default, previously `content`)
'ext' => ['md', 'markdown', 'mdown', 'mkdn', 'mkd', 'text', 'txt'], // supported files formats, by extension
'exclude' => ['vendor', 'node_modules'], // directories, paths and files name to exclude (accepts globs, strings and regexes)
'sortby' => 'date', // default collections sort method
//'sortby' => [
// 'variable' => 'date', // date|updated|title|weight
// 'desc_title' => false, // false|true
// 'reverse' => false, // false|true
//],
'frontmatter' => [
'format' => 'yaml', // front matter format: `yaml`, `ini`, `toml` or `json` (`yaml` by default)
],
Expand Down
8 changes: 4 additions & 4 deletions docs/2-Content.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
description: "Create content and organize it."
date: 2021-05-07
updated: 2023-09-20
updated: 2023-12-20
-->
# Content

Expand Down Expand Up @@ -709,13 +709,13 @@ sortby: title
---
```

**Options:**
**More options:**

```yaml
---
sortby:
variable: date # date, updated, title or weight
desc_title: false # used with date or updated variable to sort by desc title order if items have same date
variable: date # "date", "updated", "title" or "weight"
desc_title: false # used with "date" or "updated" variable value to sort by desc title order if items have the same date
reverse: false # reversed if true
---
```
Expand Down
7 changes: 6 additions & 1 deletion docs/4-Configuration.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!--
description: "Configure your website."
date: 2021-05-07
updated: 2023-12-11
updated: 2023-12-20
-->
# Configuration

Expand Down Expand Up @@ -600,6 +600,11 @@ pages:
dir: pages # pages files directory (`pages` by default, previously `content`)
ext: [md, markdown, mdown, mkdn, mkd, text, txt] # supported files formats, by extension
exclude: [vendor, node_modules] # directories, paths and files name to exclude (accepts globs, strings and regexes)
sortby: date # default collections sort method ("date" by default)
#sortby:
# variable: date # date|updated|title|weight
# desc_title: false # false|true
# reverse: false # false|true
```

#### frontmatter
Expand Down
77 changes: 48 additions & 29 deletions src/Collection/Page/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
namespace Cecil\Collection\Page;

use Cecil\Collection\Collection as CecilCollection;
use Cecil\Exception\RuntimeException;

/**
* Class Collection.
Expand Down Expand Up @@ -46,34 +47,54 @@ public function all(): self
}

/**
* Sorts pages by date (or 'updated' date): the most recent first.
*
* @param array|string $options
* Sorts pages by.
*/
public function sortByDate($options = null): self
public function sortBy(array|string|null $options): self
{
// backward compatibility
/*
* $options: date|updated|title|weight
* $options:
* variable: date|updated|title|weight
* desc_title: false|true
* reverse: false|true
*/
$sortBy = \is_string($options) ? $options : $options['variable'] ?? 'date';
$sortMethod = sprintf('sortBy%s', ucfirst(str_replace('updated', 'date', $sortBy)));
if (!method_exists($this, $sortMethod)) {
throw new RuntimeException(sprintf('"%s" is not a valid value for `sortby` to sort collection "%s".', $sortBy, $this->getId()));
}

return $this->$sortMethod($options);
}

/**
* Sorts pages by date (or 'updated'): the most recent first.
*/
public function sortByDate(array|string|null $options = null): self
{
$opt = [];
// backward compatibility (i.e. $options = 'updated')
if (\is_string($options)) {
$options['variable'] = $options;
$opt['variable'] = $options;
}
// options
$options['variable'] = $options['variable'] ?? 'date';
$options['descTitle'] = $options['descTitle'] ?? false;
$options['reverse'] = $options['reverse'] ?? false;

$pages = $this->usort(function ($a, $b) use ($options) {
if ($a[$options['variable']] == $b[$options['variable']]) {
$opt['variable'] = $options['variable'] ?? 'date';
$opt['descTitle'] = $options['descTitle'] ?? false;
$opt['reverse'] = $options['reverse'] ?? false;
// sort
$pages = $this->usort(function ($a, $b) use ($opt) {
if ($a[$opt['variable']] == $b[$opt['variable']]) {
// if dates are equal and "descTitle" is true
if ($options['descTitle'] && (isset($a['title']) && isset($b['title']))) {
if ($opt['descTitle'] && (isset($a['title']) && isset($b['title']))) {
return strnatcmp($b['title'], $a['title']);
}

return 0;
}

return $a[$options['variable']] > $b[$options['variable']] ? -1 : 1;
return $a[$opt['variable']] > $b[$opt['variable']] ? -1 : 1;
});
if ($options['reverse']) {
if ($opt['reverse']) {
$pages = $pages->reverse();
}

Expand All @@ -83,34 +104,32 @@ public function sortByDate($options = null): self
/**
* Sorts pages by title (natural sort).
*/
public function sortByTitle($options = null): self
public function sortByTitle(array|string|null $options = null): self
{
$opt = [];
// options
if (!isset($options['reverse'])) {
$options['reverse'] = false;
}

return $this->usort(function ($a, $b) use ($options) {
return ($options['reverse'] ? -1 : 1) * strnatcmp($a['title'], $b['title']);
$opt['reverse'] = $options['reverse'] ?? false;
// sort
return $this->usort(function ($a, $b) use ($opt) {
return ($opt['reverse'] ? -1 : 1) * strnatcmp($a['title'], $b['title']);
});
}

/**
* Sorts by weight (the heaviest first).
*/
public function sortByWeight($options = null): self
public function sortByWeight(array|string|null $options = null): self
{
$opt = [];
// options
if (!isset($options['reverse'])) {
$options['reverse'] = false;
}

return $this->usort(function ($a, $b) use ($options) {
$opt['reverse'] = $options['reverse'] ?? false;
// sort
return $this->usort(function ($a, $b) use ($opt) {
if ($a['weight'] == $b['weight']) {
return 0;
}

return ($options['reverse'] ? -1 : 1) * ($a['weight'] < $b['weight'] ? -1 : 1);
return ($opt['reverse'] ? -1 : 1) * ($a['weight'] < $b['weight'] ? -1 : 1);
});
}

Expand Down
12 changes: 6 additions & 6 deletions src/Generator/Homepage.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ public function generate(): void
$subPages = $this->builder->getPages()->get((string) $page->getVariable('pagesfrom'))->getPages();
}
if ($subPages instanceof \Cecil\Collection\Page\Collection) {
// sorts
$pages = $subPages->sortByDate();
// sorts pages
$pages = $subPages->sortBy($this->config->get('pages.sortby'));
if ($page->hasVariable('sortby')) {
$sortMethod = sprintf('sortBy%s', ucfirst((string) $page->getVariable('sortby')));
if (!method_exists($pages, $sortMethod)) {
throw new RuntimeException(sprintf('In page "%s" "%s" is not a valid value for "sortby" variable.', $page->getId(), $page->getVariable('sortby')));
try {
$pages = $pages->sortBy($page->getVariable('sortby'));
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('In page "%s", %s', $page->getId(), $e->getMessage()));
}
$pages = $pages->$sortMethod();
}
$page->setPages($pages);
if ($pages->first()) {
Expand Down
21 changes: 14 additions & 7 deletions src/Generator/Section.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ public function generate(): void
if ($this->builder->getPages()->has($pageId)) {
$page = clone $this->builder->getPages()->get($pageId);
}
$pages = new PagesCollection("section-$pageId", $pagesAsArray);
$subPages = new PagesCollection("section-$pageId", $pagesAsArray);
// cascade variables
if ($page->hasVariable('cascade')) {
$cascade = $page->getVariable('cascade');
$pages->map(function (Page $page) use ($cascade) {
$subPages->map(function (Page $page) use ($cascade) {
foreach ($cascade as $key => $value) {
if (!$page->hasVariable($key)) {
$page->setVariable($key, $value);
Expand All @@ -70,11 +70,18 @@ public function generate(): void
});
}
// sorts pages
$pages = self::sortSubPages($page, $pages);
$pages = $subPages->sortBy($this->config->get('pages.sortby'));
if ($page->hasVariable('sortby')) {
try {
$pages = $pages->sortBy($page->getVariable('sortby'));
} catch (RuntimeException $e) {
throw new RuntimeException(sprintf('In page "%s", %s', $page->getId(), $e->getMessage()));
}
}
// adds navigation links (excludes taxonomy pages)
$sortby = $page->getVariable('sortby')['variable'] ?? $page->getVariable('sortby') ?? 'date';
$sortBy = $page->getVariable('sortby')['variable'] ?? $page->getVariable('sortby') ?? $this->config->get('pages.sortby') ?? 'date';
if (!\in_array($page->getId(), array_keys((array) $this->config->get('taxonomies')))) {
$this->addNavigationLinks($pages, $sortby, $page->getVariable('circular'));
$this->addNavigationLinks($pages, $sortBy, $page->getVariable('circular') ?? false);
}
// creates page for each section
$page->setType(Type::SECTION->value)
Expand Down Expand Up @@ -134,10 +141,10 @@ public static function sortSubPages(Page $page, PagesCollection $pages): PagesCo
/**
* Adds navigation (next and prev) to section subpages.
*/
protected function addNavigationLinks(PagesCollection $pages, string $sort = null, $circular = false): void
protected function addNavigationLinks(PagesCollection $pages, string|null $sortBy = null, bool $circular = false): void
{
$pagesAsArray = $pages->toArray();
if ($sort === null || $sort == 'date' || $sort == 'updated') {
if ($sortBy === null || $sortBy == 'date' || $sortBy == 'updated') {
$pagesAsArray = array_reverse($pagesAsArray);
}
$count = \count($pagesAsArray);
Expand Down

0 comments on commit cb72c12

Please sign in to comment.