Last active
June 29, 2020 17:04
-
-
Save fabianmu/5f73a6c2303e08add4e00dc2e548ef2d to your computer and use it in GitHub Desktop.
unique slugs for https://github.com/agentejo/cockpit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// this is in the `/config` folder | |
$app->on("collections.save.before.aktuelles", function($name, &$entry, $isUpdate) use ($app) { | |
// generate slug on create only or when an existing one is empty | |
if (!$isUpdate || ($isUpdate && trim($entry['slug']) == '')) { | |
// generate slug based on entry name | |
$slug = Str::slug($entry['name']); | |
// count existing entires in collection with given $slug | |
$entries = count($app->module('collections')->find('aktuelles', [ | |
'filter' => [ | |
'slug' => $slug | |
], | |
'limit' => 1 | |
])); | |
// if slug is existing already, postfix with incremental count | |
if ($entries > 0) { | |
$slug = "{$slug}-{$entries}"; | |
} | |
$entry['slug'] = $slug; | |
} | |
}); | |
// below code taken from https://github.com/laravel/framework/blob/5.6/src/Illuminate/Support/Str.php and adopted to work as simple non-dependeny class for slug-creation only | |
class Str | |
{ | |
public static function slug($title, $separator = '-', $language = 'en') | |
{ | |
$title = static::ascii($title, $language); | |
// Convert all dashes/underscores into separator | |
$flip = $separator == '-' ? '_' : '-'; | |
$title = preg_replace('!['.preg_quote($flip).']+!u', $separator, $title); | |
// Replace @ with the word 'at' | |
$title = str_replace('@', $separator.'at'.$separator, $title); | |
// Remove all characters that are not the separator, letters, numbers, or whitespace. | |
$title = preg_replace('![^'.preg_quote($separator).'\pL\pN\s]+!u', '', mb_strtolower($title)); | |
// Replace all separator characters and whitespace by a single separator | |
$title = preg_replace('!['.preg_quote($separator).'\s]+!u', $separator, $title); | |
return trim($title, $separator); | |
} | |
/** | |
* Transliterate a UTF-8 value to ASCII. | |
* | |
* @param string $value | |
* @param string $language | |
* @return string | |
*/ | |
public static function ascii($value, $language = 'en') | |
{ | |
$languageSpecific = static::languageSpecificCharsArray($language); | |
if (! is_null($languageSpecific)) { | |
$value = str_replace($languageSpecific[0], $languageSpecific[1], $value); | |
} | |
foreach (static::charsArray() as $key => $val) { | |
$value = str_replace($val, $key, $value); | |
} | |
return preg_replace('/[^\x20-\x7E]/u', '', $value); | |
} | |
/** | |
* Returns the language specific replacements for the ascii method. | |
* | |
* Note: Adapted from Stringy\Stringy. | |
* | |
* @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt | |
* | |
* @param string $language | |
* @return array|null | |
*/ | |
protected static function languageSpecificCharsArray($language) | |
{ | |
static $languageSpecific; | |
if (! isset($languageSpecific)) { | |
$languageSpecific = [ | |
'bg' => [ | |
['х', 'Х', 'щ', 'Щ', 'ъ', 'Ъ', 'ь', 'Ь'], | |
['h', 'H', 'sht', 'SHT', 'a', 'А', 'y', 'Y'], | |
], | |
'de' => [ | |
['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü'], | |
['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], | |
], | |
]; | |
} | |
return $languageSpecific[$language] ?? null; | |
} | |
/** | |
* Returns the replacements for the ascii method. | |
* | |
* Note: Adapted from Stringy\Stringy. | |
* | |
* @see https://github.com/danielstjules/Stringy/blob/3.1.0/LICENSE.txt | |
* | |
* @return array | |
*/ | |
protected static function charsArray() | |
{ | |
static $charsArray; | |
if (isset($charsArray)) { | |
return $charsArray; | |
} | |
return $charsArray = [ | |
'0' => ['°', '₀', '۰', '0'], | |
'1' => ['¹', '₁', '۱', '1'], | |
'2' => ['²', '₂', '۲', '2'], | |
'3' => ['³', '₃', '۳', '3'], | |
'4' => ['⁴', '₄', '۴', '٤', '4'], | |
'5' => ['⁵', '₅', '۵', '٥', '5'], | |
'6' => ['⁶', '₆', '۶', '٦', '6'], | |
'7' => ['⁷', '₇', '۷', '7'], | |
'8' => ['⁸', '₈', '۸', '8'], | |
'9' => ['⁹', '₉', '۹', '9'], | |
'a' => ['à', 'á', 'ả', 'ã', 'ạ', 'ă', 'ắ', 'ằ', 'ẳ', 'ẵ', 'ặ', 'â', 'ấ', 'ầ', 'ẩ', 'ẫ', 'ậ', 'ā', 'ą', 'å', 'α', 'ά', 'ἀ', 'ἁ', 'ἂ', 'ἃ', 'ἄ', 'ἅ', 'ἆ', 'ἇ', 'ᾀ', 'ᾁ', 'ᾂ', 'ᾃ', 'ᾄ', 'ᾅ', 'ᾆ', 'ᾇ', 'ὰ', 'ά', 'ᾰ', 'ᾱ', 'ᾲ', 'ᾳ', 'ᾴ', 'ᾶ', 'ᾷ', 'а', 'أ', 'အ', 'ာ', 'ါ', 'ǻ', 'ǎ', 'ª', 'ა', 'अ', 'ا', 'a', 'ä'], | |
'b' => ['б', 'β', 'ب', 'ဗ', 'ბ', 'b'], | |
'c' => ['ç', 'ć', 'č', 'ĉ', 'ċ', 'c'], | |
'd' => ['ď', 'ð', 'đ', 'ƌ', 'ȡ', 'ɖ', 'ɗ', 'ᵭ', 'ᶁ', 'ᶑ', 'д', 'δ', 'د', 'ض', 'ဍ', 'ဒ', 'დ', 'd'], | |
'e' => ['é', 'è', 'ẻ', 'ẽ', 'ẹ', 'ê', 'ế', 'ề', 'ể', 'ễ', 'ệ', 'ë', 'ē', 'ę', 'ě', 'ĕ', 'ė', 'ε', 'έ', 'ἐ', 'ἑ', 'ἒ', 'ἓ', 'ἔ', 'ἕ', 'ὲ', 'έ', 'е', 'ё', 'э', 'є', 'ə', 'ဧ', 'ေ', 'ဲ', 'ე', 'ए', 'إ', 'ئ', 'e'], | |
'f' => ['ф', 'φ', 'ف', 'ƒ', 'ფ', 'f'], | |
'g' => ['ĝ', 'ğ', 'ġ', 'ģ', 'г', 'ґ', 'γ', 'ဂ', 'გ', 'گ', 'g'], | |
'h' => ['ĥ', 'ħ', 'η', 'ή', 'ح', 'ه', 'ဟ', 'ှ', 'ჰ', 'h'], | |
'i' => ['í', 'ì', 'ỉ', 'ĩ', 'ị', 'î', 'ï', 'ī', 'ĭ', 'į', 'ı', 'ι', 'ί', 'ϊ', 'ΐ', 'ἰ', 'ἱ', 'ἲ', 'ἳ', 'ἴ', 'ἵ', 'ἶ', 'ἷ', 'ὶ', 'ί', 'ῐ', 'ῑ', 'ῒ', 'ΐ', 'ῖ', 'ῗ', 'і', 'ї', 'и', 'ဣ', 'ိ', 'ီ', 'ည်', 'ǐ', 'ი', 'इ', 'ی', 'i'], | |
'j' => ['ĵ', 'ј', 'Ј', 'ჯ', 'ج', 'j'], | |
'k' => ['ķ', 'ĸ', 'к', 'κ', 'Ķ', 'ق', 'ك', 'က', 'კ', 'ქ', 'ک', 'k'], | |
'l' => ['ł', 'ľ', 'ĺ', 'ļ', 'ŀ', 'л', 'λ', 'ل', 'လ', 'ლ', 'l'], | |
'm' => ['м', 'μ', 'م', 'မ', 'მ', 'm'], | |
'n' => ['ñ', 'ń', 'ň', 'ņ', 'ʼn', 'ŋ', 'ν', 'н', 'ن', 'န', 'ნ', 'n'], | |
'o' => ['ó', 'ò', 'ỏ', 'õ', 'ọ', 'ô', 'ố', 'ồ', 'ổ', 'ỗ', 'ộ', 'ơ', 'ớ', 'ờ', 'ở', 'ỡ', 'ợ', 'ø', 'ō', 'ő', 'ŏ', 'ο', 'ὀ', 'ὁ', 'ὂ', 'ὃ', 'ὄ', 'ὅ', 'ὸ', 'ό', 'о', 'و', 'θ', 'ို', 'ǒ', 'ǿ', 'º', 'ო', 'ओ', 'o', 'ö'], | |
'p' => ['п', 'π', 'ပ', 'პ', 'پ', 'p'], | |
'q' => ['ყ', 'q'], | |
'r' => ['ŕ', 'ř', 'ŗ', 'р', 'ρ', 'ر', 'რ', 'r'], | |
's' => ['ś', 'š', 'ş', 'с', 'σ', 'ș', 'ς', 'س', 'ص', 'စ', 'ſ', 'ს', 's'], | |
't' => ['ť', 'ţ', 'т', 'τ', 'ț', 'ت', 'ط', 'ဋ', 'တ', 'ŧ', 'თ', 'ტ', 't'], | |
'u' => ['ú', 'ù', 'ủ', 'ũ', 'ụ', 'ư', 'ứ', 'ừ', 'ử', 'ữ', 'ự', 'û', 'ū', 'ů', 'ű', 'ŭ', 'ų', 'µ', 'у', 'ဉ', 'ု', 'ူ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'უ', 'उ', 'u', 'ў', 'ü'], | |
'v' => ['в', 'ვ', 'ϐ', 'v'], | |
'w' => ['ŵ', 'ω', 'ώ', 'ဝ', 'ွ', 'w'], | |
'x' => ['χ', 'ξ', 'x'], | |
'y' => ['ý', 'ỳ', 'ỷ', 'ỹ', 'ỵ', 'ÿ', 'ŷ', 'й', 'ы', 'υ', 'ϋ', 'ύ', 'ΰ', 'ي', 'ယ', 'y'], | |
'z' => ['ź', 'ž', 'ż', 'з', 'ζ', 'ز', 'ဇ', 'ზ', 'z'], | |
'aa' => ['ع', 'आ', 'آ'], | |
'ae' => ['æ', 'ǽ'], | |
'ai' => ['ऐ'], | |
'ch' => ['ч', 'ჩ', 'ჭ', 'چ'], | |
'dj' => ['ђ', 'đ'], | |
'dz' => ['џ', 'ძ'], | |
'ei' => ['ऍ'], | |
'gh' => ['غ', 'ღ'], | |
'ii' => ['ई'], | |
'ij' => ['ij'], | |
'kh' => ['х', 'خ', 'ხ'], | |
'lj' => ['љ'], | |
'nj' => ['њ'], | |
'oe' => ['ö', 'œ', 'ؤ'], | |
'oi' => ['ऑ'], | |
'oii' => ['ऒ'], | |
'ps' => ['ψ'], | |
'sh' => ['ш', 'შ', 'ش'], | |
'shch' => ['щ'], | |
'ss' => ['ß'], | |
'sx' => ['ŝ'], | |
'th' => ['þ', 'ϑ', 'ث', 'ذ', 'ظ'], | |
'ts' => ['ц', 'ც', 'წ'], | |
'ue' => ['ü'], | |
'uu' => ['ऊ'], | |
'ya' => ['я'], | |
'yu' => ['ю'], | |
'zh' => ['ж', 'ჟ', 'ژ'], | |
'(c)' => ['©'], | |
'A' => ['Á', 'À', 'Ả', 'Ã', 'Ạ', 'Ă', 'Ắ', 'Ằ', 'Ẳ', 'Ẵ', 'Ặ', 'Â', 'Ấ', 'Ầ', 'Ẩ', 'Ẫ', 'Ậ', 'Å', 'Ā', 'Ą', 'Α', 'Ά', 'Ἀ', 'Ἁ', 'Ἂ', 'Ἃ', 'Ἄ', 'Ἅ', 'Ἆ', 'Ἇ', 'ᾈ', 'ᾉ', 'ᾊ', 'ᾋ', 'ᾌ', 'ᾍ', 'ᾎ', 'ᾏ', 'Ᾰ', 'Ᾱ', 'Ὰ', 'Ά', 'ᾼ', 'А', 'Ǻ', 'Ǎ', 'A', 'Ä'], | |
'B' => ['Б', 'Β', 'ब', 'B'], | |
'C' => ['Ç', 'Ć', 'Č', 'Ĉ', 'Ċ', 'C'], | |
'D' => ['Ď', 'Ð', 'Đ', 'Ɖ', 'Ɗ', 'Ƌ', 'ᴅ', 'ᴆ', 'Д', 'Δ', 'D'], | |
'E' => ['É', 'È', 'Ẻ', 'Ẽ', 'Ẹ', 'Ê', 'Ế', 'Ề', 'Ể', 'Ễ', 'Ệ', 'Ë', 'Ē', 'Ę', 'Ě', 'Ĕ', 'Ė', 'Ε', 'Έ', 'Ἐ', 'Ἑ', 'Ἒ', 'Ἓ', 'Ἔ', 'Ἕ', 'Έ', 'Ὲ', 'Е', 'Ё', 'Э', 'Є', 'Ə', 'E'], | |
'F' => ['Ф', 'Φ', 'F'], | |
'G' => ['Ğ', 'Ġ', 'Ģ', 'Г', 'Ґ', 'Γ', 'G'], | |
'H' => ['Η', 'Ή', 'Ħ', 'H'], | |
'I' => ['Í', 'Ì', 'Ỉ', 'Ĩ', 'Ị', 'Î', 'Ï', 'Ī', 'Ĭ', 'Į', 'İ', 'Ι', 'Ί', 'Ϊ', 'Ἰ', 'Ἱ', 'Ἳ', 'Ἴ', 'Ἵ', 'Ἶ', 'Ἷ', 'Ῐ', 'Ῑ', 'Ὶ', 'Ί', 'И', 'І', 'Ї', 'Ǐ', 'ϒ', 'I'], | |
'J' => ['J'], | |
'K' => ['К', 'Κ', 'K'], | |
'L' => ['Ĺ', 'Ł', 'Л', 'Λ', 'Ļ', 'Ľ', 'Ŀ', 'ल', 'L'], | |
'M' => ['М', 'Μ', 'M'], | |
'N' => ['Ń', 'Ñ', 'Ň', 'Ņ', 'Ŋ', 'Н', 'Ν', 'N'], | |
'O' => ['Ó', 'Ò', 'Ỏ', 'Õ', 'Ọ', 'Ô', 'Ố', 'Ồ', 'Ổ', 'Ỗ', 'Ộ', 'Ơ', 'Ớ', 'Ờ', 'Ở', 'Ỡ', 'Ợ', 'Ø', 'Ō', 'Ő', 'Ŏ', 'Ο', 'Ό', 'Ὀ', 'Ὁ', 'Ὂ', 'Ὃ', 'Ὄ', 'Ὅ', 'Ὸ', 'Ό', 'О', 'Θ', 'Ө', 'Ǒ', 'Ǿ', 'O', 'Ö'], | |
'P' => ['П', 'Π', 'P'], | |
'Q' => ['Q'], | |
'R' => ['Ř', 'Ŕ', 'Р', 'Ρ', 'Ŗ', 'R'], | |
'S' => ['Ş', 'Ŝ', 'Ș', 'Š', 'Ś', 'С', 'Σ', 'S'], | |
'T' => ['Ť', 'Ţ', 'Ŧ', 'Ț', 'Т', 'Τ', 'T'], | |
'U' => ['Ú', 'Ù', 'Ủ', 'Ũ', 'Ụ', 'Ư', 'Ứ', 'Ừ', 'Ử', 'Ữ', 'Ự', 'Û', 'Ū', 'Ů', 'Ű', 'Ŭ', 'Ų', 'У', 'Ǔ', 'Ǖ', 'Ǘ', 'Ǚ', 'Ǜ', 'U', 'Ў', 'Ü'], | |
'V' => ['В', 'V'], | |
'W' => ['Ω', 'Ώ', 'Ŵ', 'W'], | |
'X' => ['Χ', 'Ξ', 'X'], | |
'Y' => ['Ý', 'Ỳ', 'Ỷ', 'Ỹ', 'Ỵ', 'Ÿ', 'Ῠ', 'Ῡ', 'Ὺ', 'Ύ', 'Ы', 'Й', 'Υ', 'Ϋ', 'Ŷ', 'Y'], | |
'Z' => ['Ź', 'Ž', 'Ż', 'З', 'Ζ', 'Z'], | |
'AE' => ['Æ', 'Ǽ'], | |
'Ch' => ['Ч'], | |
'Dj' => ['Ђ'], | |
'Dz' => ['Џ'], | |
'Gx' => ['Ĝ'], | |
'Hx' => ['Ĥ'], | |
'Ij' => ['IJ'], | |
'Jx' => ['Ĵ'], | |
'Kh' => ['Х'], | |
'Lj' => ['Љ'], | |
'Nj' => ['Њ'], | |
'Oe' => ['Œ'], | |
'Ps' => ['Ψ'], | |
'Sh' => ['Ш'], | |
'Shch' => ['Щ'], | |
'Ss' => ['ẞ'], | |
'Th' => ['Þ'], | |
'Ts' => ['Ц'], | |
'Ya' => ['Я'], | |
'Yu' => ['Ю'], | |
'Zh' => ['Ж'], | |
' ' => ["\xC2\xA0", "\xE2\x80\x80", "\xE2\x80\x81", "\xE2\x80\x82", "\xE2\x80\x83", "\xE2\x80\x84", "\xE2\x80\x85", "\xE2\x80\x86", "\xE2\x80\x87", "\xE2\x80\x88", "\xE2\x80\x89", "\xE2\x80\x8A", "\xE2\x80\xAF", "\xE2\x81\x9F", "\xE3\x80\x80", "\xEF\xBE\xA0"], | |
]; | |
} | |
} |
also instead of count($app->module('collections')->find(...))
you can also use $app->module('collections')->count('aktuelles', ['slug' => $slug])
Changes with @aheinze suggestions:
(Just change the "XXX" occurrences with your collection name and "YYY" occurrences with the entry you want your slug to be based on)
<?php
// this is in the `/config` folder
// collection: XXX
// slug is created bt reading this field: YYY
$app->on("collections.save.before.XXX", function($YYY, &$entry, $isUpdate) use ($app) {
// generate slug on create only or when an existing one is empty
if (!$isUpdate || ($isUpdate && trim($entry['slug']) == '')) {
// generate slug based on defined entry
$slug = $app->helper('utils')->sluggify($entry['YYY']);
// count existing entires in collection with given $slug
$entries = $app->module('collections')->count('XXX', ['slug' => $slug]);
// if slug is existing already, postfix with incremental count
if ($entries > 0) {
$slug = "{$slug}-{$entries}";
}
$entry['slug'] = $slug;
}
});
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
instead of
Str::slug($entry['name'])
you can also use the built-in sluggify helper function e.g$app->helper('utils')->sluggify($entry['name'])