Skip to content

Commit

Permalink
Merge pull request #41 from sachbearbeiter/main
Browse files Browse the repository at this point in the history
initial v4 commit (various issues)
  • Loading branch information
sachbearbeiter authored Nov 7, 2024
2 parents 6ac9c48 + a9f0839 commit 9d15885
Show file tree
Hide file tree
Showing 14 changed files with 686 additions and 130 deletions.
13 changes: 11 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,20 @@ fields:
navigation:
label: Navigation
type: navigation
levels: 5
levels: 10
help: Description of menu or where it is used
width: 1/2
```
Minimum blueprint:
```yaml
fields:
navigation:
label: Navigation
type: navigation
```
Two Field methods are included which will output the menu regardless of how many levels deep you go:
```php
Expand Down Expand Up @@ -85,7 +94,7 @@ If you would like full control of your menu and would prefer to use a foreach to

## Info

Nesting limit is set as default to 5, to allow further levels adjust the levels option in the blueprint
Nesting limit is set as default to 10, to allow different levels adjust the levels option in the blueprint

## Contributing

Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "chrisbeluga/kirby-navigation",
"description": "Kirby 3 field for hierarchical menus with drag & drop level indentation.",
"description": "Kirby 4 field for hierarchical menus with drag & drop level indentation.",
"type": "kirby-plugin",
"version": "3.0.1",
"version": "4.0.1",
"license": "MIT",
"homepage": "https://github.com/chrisbeluga/kirby-navigation",
"authors": [
Expand Down
110 changes: 76 additions & 34 deletions config/api.php
Original file line number Diff line number Diff line change
@@ -1,41 +1,83 @@
<?php
use Kirby\Uuid\Uuids;
/**
* Good to know:
* - stored Kirby links always have 'id' values, Custom links never have that
* - stored Kirby links may have 'uuid_uri' values, Custom links never have that
* - The uuid_uri can identify a page even after the page slug changes,
* so it is the preferred way of identification.
* - If uuid_uri value is not available for any reason, the plugin uses the 'id' value
* to find the desired page
* - The 'uuid' value used elsewhere in the plugin is not the same as 'uuid_uri' value.
* The 'uuid' value is kept for compatibility reasons.
*/

return function () {
return [
[
'pattern' => 'listings/(:all)',
'method' => 'GET',
'action' => function ($all) {
$content = [];
$breadcrumbs = [];
$getData = $all !== 'site' ? true : false;
$data = $getData ? page($all) : site();
return [
[
'pattern' => 'listings/(:alpha)/(:all)',
'method' => 'GET',
'action' => function ($language_code, $path) {
$content = [];
$breadcrumbs = [];
$getData = $path !== 'site' ? true : false;
$data = $getData ? page($path) : site();

if ($data->hasChildren()) {
if ($getData) {
foreach ($data->children()->first()->parents()->flip() as $parent) {
array_push($breadcrumbs,[
'id' => $parent->id(),
'title' => $parent->title()->value()
]);
}
}
$multilang = $this->kirby()->languages()->isNotEmpty();
if ($multilang) {
if ($language_code=='default') {
// default language, use item title and url without translation
$multilang=false;
}
elseif (!$this->kirby()->languages()->find($language_code)) {
// invalid language, do nothing, just return an empty array
$data=null;
}
}
if (($data != null) && $data->hasChildren()) {
if ($getData) {
foreach ($data->children()->first()->parents()->flip() as $parent) {
if ($multilang && ($parent->content($language_code)->title()->value() != null)) {
$title=$parent->content($language_code)->title()->value();
}
else {
$title = $parent->title()->value();
}
array_push($breadcrumbs,[
'id' => $parent->id(),
'title' => $title,
]);
}
}

foreach ($data->children() as $item) {
array_push($content, [
'id' => $item->id(),
'url' => $item->url(),
'text' => $item->title()->value(),
'count' => $item->index()->count(),
'children' => []
]);
}
}
return [
'content' => $content,
'breadcrumbs' => $breadcrumbs,
];
foreach ($data->children() as $item) {
$title = $item->title()->value();
if ($multilang && ($item->content($language_code)->title()->value() != null)) {
$title=$item->content($language_code)->title()->value();
}
],
];
array_push($content, [
// Values for page identification
'type' => 'page',
'uuid_uri' => Uuids::enabled() ? $item->uuid()->toString() : '',
'id' => $item->id(),
// Language-specific values that may change due to editing
$language_code . '_page_url' => $multilang ? $item->url($language_code) : $item->url(),
$language_code . '_page_title' => $title,
// Default values of page links that prop.php also provides
$language_code . '_link_text' => '',
$language_code . '_link_title' => '',
'popup' => false,
'children' => [],
// Temporary helper values that will not be saved
'count' => $item->index()->count(),
]);
}
}
return [
'content' => $content,
'breadcrumbs' => $breadcrumbs,
];
}
],
];
};
10 changes: 7 additions & 3 deletions config/methods.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php

use Kirby\Uuid\Uuids;
return [
'toNavigationArray' => function ($field) {
$items = [];
Expand All @@ -9,10 +9,10 @@
if ($child->children()->isNotEmpty()) {
array_push($children, $child->children());
}

array_push($items, [
'id' => $child->id(),
'url' => $child->url()->value(),
'uuid_uri' => Uuids::enabled() ? $child->uuid()->value() : '',
'text' => $child->text()->value(),
'title' => $child->title()->value(),
'popup' => $child->popup()->toBool(),
Expand All @@ -23,8 +23,12 @@
return $items;
},
'toNavigationMarkup' => function ($field) {
// Refresh items to get the current multilang URL and page titles
require __DIR__ . '/../includes/refresh_item.inc.php';
$items=$refresh_items($field->yaml(), $field->key(), $field->model());
// Generate HTML
return snippet('navigation', [
'children' => $field
'children' => $items
]);
}
];
35 changes: 32 additions & 3 deletions config/props.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,36 @@
use Kirby\Data\Yaml;

return [
'value' => function ($value = []) {
return Yaml::decode($value);
},
'value' => function ($value = []) {
$items=Yaml::decode($value);

// Check whether there is an item with type 'save',
// which indicates that the data was just submitted, and
// in this case no changes should be done.
// This 'save' item is always added by props.php
// This 'save' item is always removed by the save.php
// This 'save' trick is needed, because the props.php is not only
// executed when a field is loaded, but also when it is saved, and
// otherwise it would not be possible to distinguish between the two.
$save_in_progress=FALSE;
if (is_array($items) && $items) {
foreach ($items as $item) {
if (isset($item['type']) && ($item['type']==='save')) {
// saving is in progress, do nothing.
$save_in_progress=TRUE;
break;
}
}
}
if (!$save_in_progress) {
// Refresh items to get the current multilang URL and page titles
require __DIR__ . '/../includes/refresh_item.inc.php';
$items=$refresh_items($items, $this->name(), $this->model());
// Add a 'save' item. When the 'props' values are sent to Panel,
// the Field.vue will hide this item, but it will send it back,
// and then the props.php will detect it, and save.php will ignore it.
$items[]=['type' => 'save', 'uuid' => uniqid(), 'children' => []];
}
return $items;
},
];
80 changes: 80 additions & 0 deletions config/save.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

use Kirby\Data\Yaml;
use Kirby\Uuid\Uuids;

return function ($items) {
// Use anonymous recursive function to process child items
$prepare_item = function($item) use (&$prepare_item) {
if (!is_array($item) || !isset($item['type'])) {
throw new Exception('Unexpected data found in the navigation field while saving');
}
if ($item['type'] === 'page') {
// The primary way of page identification is by 'uuid_uri',
// if not available, then by 'id'.
// Although page url and page title are saved here,
// these values will be refreshed when the field data is loaded,
//

// Do not store 'count' value (coming from api.php)
unset($item['count']);
}
// Remove the 'error' value, it will be set again when loading field values
unset($item['error']);
// prepare child items, if any
if (!empty($item['children'])) {
foreach (array_keys($item['children']) as $key) {
$item['children'][$key]=$prepare_item($item['children'][$key]);
}
}
return $item;
};

// Remove any item with type 'save',
// indicating field data that was just submitted
// This 'save' item is always added by props.php
// This 'save' item is always removed by the save.php
// This 'save' trick is needed, because the props.php is not only
// executed when a field is loaded, but also when it is saved, and
// otherwise it would not be possible to distinguish between the two.
if (is_array($items) && $items) {
foreach (array_keys($items) as $key) {
if (isset($items[$key]['type']) && ($items[$key]['type']==='save')) {
unset($items[$key]);
}
}
if ($items) {
// When the 'save' item is deleted, there may be a gap in keys
// Make sure that array keys have no gaps, to avoid JS problems
$items=array_values($items);
}
}

if (is_array($items) && $items) {
foreach (array_keys($items) as $key) {
$items[$key]=$prepare_item($items[$key]);
}
}

// Get the 'multilang' option of the field blueprint
$blueprint_field=$this->model()->blueprint()->field($this->name());
if (!empty($blueprint_field) && !empty($blueprint_field['multilang'])) {
// If 'multilang' is set in the blueprint, then data is stored
// in external yaml file, so that it can be shared between languages
$filepathTMP = tempnam(sys_get_temp_dir(), 'navigation');
if (file_put_contents($filepathTMP, Yaml::encode($items))) {
if (rename($filepathTMP, $this->model()->root() . '/kirby-navigation---' . $this->name() . '.yml')) {
// The data was successfully saved to the external file,
// so change the field data to a simple flag that will tell
// the load function to load the external file.
$items=['multilang' => TRUE];
}
else {
}
}
else {
}
@unlink($filepathTMP);
}
return $items;
};
Loading

0 comments on commit 9d15885

Please sign in to comment.