Skip to content

Instantly share code, notes, and snippets.

@faridbouchdak
Last active September 13, 2023 05:58
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save faridbouchdak/d4e0ff6e348ccb416f6b9c944a331664 to your computer and use it in GitHub Desktop.
Save faridbouchdak/d4e0ff6e348ccb416f6b9c944a331664 to your computer and use it in GitHub Desktop.
Simple slugs for collections in Cockpit CMS
<?php
/*
Simple slugs for collections in Cockpit - https://github.com/Cockpit-HQ/Cockpit
Place this code or copy this file in `/config/bootstrap.php`.
Notes:
For this to work properly the collection of your choice needs a field of type 'text' (give it any name you like) and in its options a key 'slugField' with the name of the field to generate the slug from.
When you create/update an entry, cockpit generates and saves the (unique) slug IF the field to generate the slug from exists AND is not empty AND field slug is empty.
Important: Don't use the builtin option to sluggify fields via options `{"slug": true}`.
This code is a Frankenstein-version of several properly written files.
(please don't blame anybody for my copy&paste actions, thank you!)
Thanks to https://github.com/fabianmu, https://github.com/aheinze, https://github.com/raffaelj
and the community (https://discourse.getcockpit.com/)
*/
# events
$app->on('content.item.save.before', function($modelName, &$data, $isUpdate) {
# save name of collection/singleton
$model = $this->module('content')->model($modelName);
$collection = $model['type'] == 'singleton' ? 'content/singletons' : "content/collections/{$modelName}";
$fields = $model['fields'] ?? [];
// get all the translations from cockpit (locales)
$translations = [];
foreach ($this->helper('locales')->locales(true) as $translation => $loc) {
if ($translation === "default") {
$translations[] = "";
} else {
$translations[] = "_".$translation;
}
}
foreach ($fields as $field) {
# check if slug field is set and referenced field is in data
if (isset($field['opts']['slugField'], $data[$field['opts']['slugField']])) {
foreach ($translations as $translation) {
// check if referenced field is not empty
if (!empty($data[$field['opts']['slugField'].$translation])) {
if (empty($data[$field['name'].$translation])) {
# sluggify referenced field
$slug = $this->helper('utils')->sluggify($data[$field['opts']['slugField'].$translation]);
} else {
# sluggify field that already contains slug-value
$slug = $this->helper('utils')->sluggify($data[$field['name'].$translation]);
}
# unique slug: count existing entries in collection with given $slug
$entries = $this->dataStorage->find($collection, [
'filter' => [
'$or' => [
[$field['name'].$translation => ['$regex' => $slug, '$options' => 'i']],
],
]
])->toArray();
// remove entry with same '_id' (because that's considered an update)
foreach ($entries as $entry_key => $entry) {
if ($entry['_id'] == $data['_id']) {
array_splice($entries, $entry_key, 1);
}
}
$entries=count($entries);
# if slug exists already in model, add an incremental count to slug and update slug-field
if ($entries > 0) {
$data[$field['name'].$translation] = $slug."-".$entries;
} else {
# update slug-field
$data[$field['name'].$translation] = $slug;
}
}
}
# No need to trigger a "save" anymore, because we hook into the content.item.save.before event!
//$this->dataStorage->save($collection, $data);
break;
}
}
});
@Cryptospy
Copy link

for some reason its not working.. getting error 500. using latest cockpit

@faridbouchdak
Copy link
Author

faridbouchdak commented Jul 27, 2023 via email

@Cryptospy
Copy link

Hi, Did you look around the issue?

@faridbouchdak
Copy link
Author

Yes, sorry for the long wait.
I can't replicate the error 500 issue.
I used a clean install of cockpit-core and this file (bootstrap.php) in its 'config' folder.
Then I created a collection with the name 'test'.
In this collection there are two fields of type 'text':

  1. 'title'
  2. 'slug'

In the options for 'slug', i added "slugField: 'title'," in the json-representation of it.

Can you replicate the above steps and try again, please?

I found a little quirck:
when there isn't a duplicate record, cockpit refreshes the slugField nicely after saving.
but, when there is a duplicate record it doesn't refreshes the slugField after saving (the data is saved correctly).
I am going to try to fix this behaviour this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment