diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..33219147 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,40 @@ +build: false +shallow_clone: true +platform: x86 +clone_folder: c:\projects\cocur\slugify + +cache: + - '%LOCALAPPDATA%\Composer\files' + +init: + - SET PATH=C:\Program Files\OpenSSL;c:\tools\php;%PATH% + +environment: + matrix: + - COMPOSER_FLAGS: "" + +install: + - cinst -y OpenSSL.Light + - cinst -y php + - cd c:\tools\php + - copy php.ini-production php.ini /Y + - echo date.timezone="UTC" >> php.ini + - echo extension_dir=ext >> php.ini + - echo extension=php_openssl.dll >> php.ini + - echo extension=php_mbstring.dll >> php.ini + - echo extension=php_fileinfo.dll >> php.ini + - echo memory_limit=1G >> php.ini + - cd c:\projects\cocur\slugify + - php -r "readfile('http://getcomposer.org/installer');" | php + - php composer.phar update %COMPOSER_FLAGS% --no-interaction --no-progress + +test_script: + - cd c:\projects\cocur\slugify + - vendor\bin\phpunit.bat --verbose + +notifications: + - provider: Webhook + url: https://webhooks.gitter.im/e/aaf55568e4629e650616 + on_build_success: false + on_build_failure: true + on_build_status_changed: true diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 3d736759..00000000 --- a/.coveralls.yml +++ /dev/null @@ -1,6 +0,0 @@ -service_name: travis-ci - -# for php-coveralls -src_dir: src -coverage_clover: build/logs/clover.xml -json_path: build/logs/coveralls-upload.json diff --git a/.travis.yml b/.travis.yml index 80b50c50..3c1a29ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,10 +11,6 @@ matrix: - php: 7.0 fast_finish: true -addons: - code_climate: - repo_token: e27c69a17c19e62d55c1ec43eecc6821b905c504e5cb5cc4ad7f8a997163447a - before_script: - sudo sh -c "echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf" - composer self-update @@ -24,10 +20,6 @@ script: - mkdir -p build/logs - ./vendor/bin/phpunit -after_script: - - php vendor/bin/coveralls -v - - php vendor/bin/test-reporter - notifications: webhooks: urls: diff --git a/Resources/rules/arabic.json b/Resources/rules/arabic.json new file mode 100644 index 00000000..e46915f1 --- /dev/null +++ b/Resources/rules/arabic.json @@ -0,0 +1,30 @@ +{ + "أ" : "a", + "ب" : "b", + "ت" : "t", + "ث" : "th", + "ج" : "g", + "ح" : "h", + "خ" : "kh", + "د" : "d", + "ذ" : "th", + "ر" : "r", + "ز" : "z", + "س" : "s", + "ش" : "sh", + "ص" : "s", + "ض" : "d", + "ط" : "t", + "ظ" : "th", + "ع" : "aa", + "غ" : "gh", + "ف" : "f", + "ق" : "k", + "ك" : "k", + "ل" : "l", + "م" : "m", + "ن" : "n", + "ه" : "h", + "و" : "o", + "ي" : "y" +} diff --git a/Resources/rules/austrian.json b/Resources/rules/austrian.json new file mode 100644 index 00000000..7753dcfc --- /dev/null +++ b/Resources/rules/austrian.json @@ -0,0 +1,9 @@ +{ + "Ä": "AE", + "Ö": "OE", + "Ü": "UE", + "ß": "sz", + "ä": "ae", + "ö": "oe", + "ü": "ue" +} diff --git a/Resources/rules/burmese.json b/Resources/rules/burmese.json new file mode 100644 index 00000000..08f5a0a0 --- /dev/null +++ b/Resources/rules/burmese.json @@ -0,0 +1,121 @@ +{ + "က": "k", + "ခ": "kh", + "ဂ": "g", + "ဃ": "ga", + "င": "ng", + "စ": "s", + "ဆ": "sa", + "ဇ": "z", + "စျ" : "za", + "ည": "ny", + "ဋ": "t", + "ဌ": "ta", + "ဍ": "d", + "ဎ": "da", + "ဏ": "na", + "တ": "t", + "ထ": "ta", + "ဒ": "d", + "ဓ": "da", + "န": "n", + "ပ": "p", + "ဖ": "pa", + "ဗ": "b", + "ဘ": "ba", + "မ": "m", + "ယ": "y", + "ရ": "ya", + "လ": "l", + "ဝ": "w", + "သ": "th", + "ဟ": "h", + "ဠ": "la", + "အ": "a", + + "ြ": "y", + "ျ": "ya", + "ွ": "w", + "ြွ": "yw", + "ျွ": "ywa", + "ှ": "h", + + "ဧ": "e", + "၏": "-e", + "ဣ": "i", + "ဤ": "-i", + "ဉ": "u", + "ဦ": "-u", + "ဩ": "aw", + "သြော" : "aw", + "ဪ": "aw", + "၍": "ywae", + "၌": "hnaik", + + "၀": "0", + "၁": "1", + "၂": "2", + "၃": "3", + "၄": "4", + "၅": "5", + "၆": "6", + "၇": "7", + "၈": "8", + "၉": "9", + + "္": "", + "့": "", + "း": "", + + "ာ": "a", + "ါ": "a", + "ေ": "e", + "ဲ": "e", + "ိ": "i", + "ီ": "i", + "ို": "o", + "ု": "u", + "ူ": "u", + "ေါင်": "aung", + "ော": "aw", + "ော်": "aw", + "ေါ": "aw", + "ေါ်": "aw", + "်": "at", + "က်": "et", + "ိုက်" : "aik", + "ောက်" : "auk", + "င်" : "in", + "ိုင်" : "aing", + "ောင်" : "aung", + "စ်" : "it", + "ည်" : "i", + "တ်" : "at", + "ိတ်" : "eik", + "ုတ်" : "ok", + "ွတ်" : "ut", + "ေတ်" : "it", + "ဒ်" : "d", + "ိုဒ်" : "ok", + "ုဒ်" : "ait", + "န်" : "an", + "ာန်" : "an", + "ိန်" : "ein", + "ုန်" : "on", + "ွန်" : "un", + "ပ်" : "at", + "ိပ်" : "eik", + "ုပ်" : "ok", + "ွပ်" : "ut", + "န်ုပ်" : "nub", + "မ်" : "an", + "ိမ်" : "ein", + "ုမ်" : "on", + "ွမ်" : "un", + "ယ်" : "e", + "ိုလ်" : "ol", + "ဉ်" : "in", + "ံ": "an", + "ိံ" : "ein", + "ုံ" : "on" +} diff --git a/Resources/rules/czech.json b/Resources/rules/czech.json new file mode 100644 index 00000000..549f8054 --- /dev/null +++ b/Resources/rules/czech.json @@ -0,0 +1,20 @@ +{ + "Č": "C", + "Ď": "D", + "Ě": "E", + "Ň": "N", + "Ř": "R", + "Š": "S", + "Ť": "T", + "Ů": "U", + "Ž": "Z", + "č": "c", + "ď": "d", + "ě": "e", + "ň": "n", + "ř": "r", + "š": "s", + "ť": "t", + "ů": "u", + "ž": "z" +} diff --git a/Resources/rules/default.json b/Resources/rules/default.json new file mode 100644 index 00000000..678d10db --- /dev/null +++ b/Resources/rules/default.json @@ -0,0 +1,180 @@ +{ + "°": 0, + "¹": 1, + "²": 2, + "³": 3, + "⁴": 4, + "⁵": 5, + "⁶": 6, + "⁷": 7, + "⁸": 8, + "⁹": 9, + + "₀": 0, + "₁": 1, + "₂": 2, + "₃": 3, + "₄": 4, + "₅": 5, + "₆": 6, + "₇": 7, + "₈": 8, + "₉": 9, + + + "æ": "ae", + "ǽ": "ae", + "À": "A", + "Á": "A", + "Â": "A", + "Ã": "A", + "Å": "AA", + "Ǻ": "A", + "Ă": "A", + "Ǎ": "A", + "Æ": "AE", + "Ǽ": "AE", + "à": "a", + "á": "a", + "â": "a", + "ã": "a", + "å": "aa", + "ǻ": "a", + "ă": "a", + "ǎ": "a", + "ª": "a", + "@": "at", + "Ĉ": "C", + "Ċ": "C", + "ĉ": "c", + "ċ": "c", + "©": "c", + "Ð": "Dj", + "Đ": "D", + "ð": "dj", + "đ": "d", + "È": "E", + "É": "E", + "Ê": "E", + "Ë": "E", + "Ĕ": "E", + "Ė": "E", + "è": "e", + "é": "e", + "ê": "e", + "ë": "e", + "ĕ": "e", + "ė": "e", + "ƒ": "f", + "Ĝ": "G", + "Ġ": "G", + "ĝ": "g", + "ġ": "g", + "Ĥ": "H", + "Ħ": "H", + "ĥ": "h", + "ħ": "h", + "Ì": "I", + "Í": "I", + "Î": "I", + "Ï": "I", + "Ĩ": "I", + "Ĭ": "I", + "Ǐ": "I", + "Į": "I", + "IJ": "IJ", + "ì": "i", + "í": "i", + "î": "i", + "ï": "i", + "ĩ": "i", + "ĭ": "i", + "ǐ": "i", + "į": "i", + "ij": "ij", + "Ĵ": "J", + "ĵ": "j", + "Ĺ": "L", + "Ľ": "L", + "Ŀ": "L", + "ĺ": "l", + "ľ": "l", + "ŀ": "l", + "Ñ": "N", + "ñ": "n", + "ʼn": "n", + "Ò": "O", + "Ô": "O", + "Õ": "O", + "Ō": "O", + "Ŏ": "O", + "Ǒ": "O", + "Ő": "O", + "Ơ": "O", + "Ø": "OE", + "Ǿ": "O", + "Œ": "OE", + "ò": "o", + "ô": "o", + "õ": "o", + "ō": "o", + "ŏ": "o", + "ǒ": "o", + "ő": "o", + "ơ": "o", + "ø": "oe", + "ǿ": "o", + "º": "o", + "œ": "oe", + "Ŕ": "R", + "Ŗ": "R", + "ŕ": "r", + "ŗ": "r", + "Ŝ": "S", + "Ș": "S", + "ŝ": "s", + "ș": "s", + "ſ": "s", + "Ţ": "T", + "Ț": "T", + "Ŧ": "T", + "Þ": "TH", + "ţ": "t", + "ț": "t", + "ŧ": "t", + "þ": "th", + "Ù": "U", + "Ú": "U", + "Û": "U", + "Ũ": "U", + "Ŭ": "U", + "Ű": "U", + "Ų": "U", + "Ư": "U", + "Ǔ": "U", + "Ǖ": "U", + "Ǘ": "U", + "Ǚ": "U", + "Ǜ": "U", + "ù": "u", + "ú": "u", + "û": "u", + "ũ": "u", + "ŭ": "u", + "ű": "u", + "ų": "u", + "ư": "u", + "ǔ": "u", + "ǖ": "u", + "ǘ": "u", + "ǚ": "u", + "ǜ": "u", + "Ŵ": "W", + "ŵ": "w", + "Ý": "Y", + "Ÿ": "Y", + "Ŷ": "Y", + "ý": "y", + "ÿ": "y", + "ŷ": "y" +} diff --git a/Resources/rules/esperanto.json b/Resources/rules/esperanto.json new file mode 100644 index 00000000..9a4e6581 --- /dev/null +++ b/Resources/rules/esperanto.json @@ -0,0 +1,14 @@ +{ + "ĉ": "cx", + "ĝ": "gx", + "ĥ": "hx", + "ĵ": "jx", + "ŝ": "sx", + "ŭ": "ux", + "Ĉ": "CX", + "Ĝ": "GX", + "Ĥ": "HX", + "Ĵ": "JX", + "Ŝ": "SX", + "Ŭ": "UX" +} diff --git a/Resources/rules/finnish.json b/Resources/rules/finnish.json new file mode 100644 index 00000000..fd35423e --- /dev/null +++ b/Resources/rules/finnish.json @@ -0,0 +1,6 @@ +{ + "Ä": "A", + "Ö": "O", + "ä": "a", + "ö": "o" +} diff --git a/Resources/rules/georgian.json b/Resources/rules/georgian.json new file mode 100644 index 00000000..2c635737 --- /dev/null +++ b/Resources/rules/georgian.json @@ -0,0 +1,35 @@ +{ + "ა": "a", + "ბ": "b", + "გ": "g", + "დ": "d", + "ე": "e", + "ვ": "v", + "ზ": "z", + "თ": "t", + "ი": "i", + "კ": "k", + "ლ": "l", + "მ": "m", + "ნ": "n", + "ო": "o", + "პ": "p", + "ჟ": "zh", + "რ": "r", + "ს": "s", + "ტ": "t", + "უ": "u", + "ფ": "f", + "ქ": "k", + "ღ": "gh", + "ყ": "q", + "შ": "sh", + "ჩ": "ch", + "ც": "ts", + "ძ": "dz", + "წ": "ts", + "ჭ": "ch", + "ხ": "kh", + "ჯ": "j", + "ჰ": "h" +} diff --git a/Resources/rules/german.json b/Resources/rules/german.json new file mode 100644 index 00000000..881b68c1 --- /dev/null +++ b/Resources/rules/german.json @@ -0,0 +1,9 @@ +{ + "Ä": "AE", + "Ö": "OE", + "Ü": "UE", + "ß": "ss", + "ä": "ae", + "ö": "oe", + "ü": "ue" +} diff --git a/Resources/rules/greek.json b/Resources/rules/greek.json new file mode 100644 index 00000000..767a223b --- /dev/null +++ b/Resources/rules/greek.json @@ -0,0 +1,111 @@ +{ + "ΑΥ": "AU", + "Αυ": "Au", + "ΟΥ": "OU", + "Ου": "Ou", + "ΕΥ": "EU", + "Ευ": "Eu", + "ΕΙ": "I", + "Ει": "I", + "ΟΙ": "I", + "Οι": "I", + "ΥΙ": "I", + "Υι": "I", + "ΑΎ": "AU", + "Αύ": "Au", + "ΟΎ": "OU", + "Ού": "Ou", + "ΕΎ": "EU", + "Εύ": "Eu", + "ΕΊ": "I", + "Εί": "I", + "ΟΊ": "I", + "Οί": "I", + "ΎΙ": "I", + "Ύι": "I", + "ΥΊ": "I", + "Υί": "I", + "αυ": "au", + "ου": "ou", + "ευ": "eu", + "ει": "i", + "οι": "i", + "υι": "i", + "αύ": "au", + "ού": "ou", + "εύ": "eu", + "εί": "i", + "οί": "i", + "ύι": "i", + "υί": "i", + "Α": "A", + "Β": "V", + "Γ": "G", + "Δ": "D", + "Ε": "E", + "Ζ": "Z", + "Η": "I", + "Θ": "Th", + "Ι": "I", + "Κ": "K", + "Λ": "L", + "Μ": "M", + "Ν": "N", + "Ξ": "X", + "Ο": "O", + "Π": "P", + "Ρ": "R", + "Σ": "S", + "Τ": "T", + "Υ": "I", + "Φ": "F", + "Χ": "Ch", + "Ψ": "Ps", + "Ω": "O", + "Ά": "A", + "Έ": "E", + "Ή": "I", + "Ί": "I", + "Ό": "O", + "Ύ": "I", + "Ϊ": "I", + "Ϋ": "I", + "ϒ": "I", + "α": "a", + "β": "v", + "γ": "g", + "δ": "d", + "ε": "e", + "ζ": "z", + "η": "i", + "θ": "th", + "ι": "i", + "κ": "k", + "λ": "l", + "μ": "m", + "ν": "n", + "ξ": "x", + "ο": "o", + "π": "p", + "ρ": "r", + "ς": "s", + "σ": "s", + "τ": "t", + "υ": "i", + "φ": "f", + "χ": "ch", + "ψ": "ps", + "ω": "o", + "ά": "a", + "έ": "e", + "ή": "i", + "ί": "i", + "ό": "o", + "ύ": "i", + "ϊ": "i", + "ϋ": "i", + "ΰ": "i", + "ώ": "o", + "ϐ": "v", + "ϑ": "th" +} diff --git a/Resources/rules/latvian.json b/Resources/rules/latvian.json new file mode 100644 index 00000000..d5b0010d --- /dev/null +++ b/Resources/rules/latvian.json @@ -0,0 +1,18 @@ +{ + "Ā": "A", + "Ē": "E", + "Ģ": "G", + "Ī": "I", + "Ķ": "K", + "Ļ": "L", + "Ņ": "N", + "Ū": "U", + "ā": "a", + "ē": "e", + "ģ": "g", + "ī": "i", + "ķ": "k", + "ļ": "l", + "ņ": "n", + "ū": "u" +} diff --git a/Resources/rules/polish.json b/Resources/rules/polish.json new file mode 100644 index 00000000..5d0c123c --- /dev/null +++ b/Resources/rules/polish.json @@ -0,0 +1,20 @@ +{ + "Ą": "A", + "Ć": "C", + "Ę": "E", + "Ł": "L", + "Ń": "N", + "Ó": "O", + "Ś": "S", + "Ź": "Z", + "Ż": "Z", + "ą": "a", + "ć": "c", + "ę": "e", + "ł": "l", + "ń": "n", + "ó": "o", + "ś": "s", + "ź": "z", + "ż": "z" +} diff --git a/Resources/rules/russian.json b/Resources/rules/russian.json new file mode 100644 index 00000000..b8b354c8 --- /dev/null +++ b/Resources/rules/russian.json @@ -0,0 +1,68 @@ +{ + "Ъ": "", + "Ь": "", + "А": "A", + "Б": "B", + "Ц": "C", + "Ч": "Ch", + "Д": "D", + "Е": "E", + "Ё": "E", + "Э": "E", + "Ф": "F", + "Г": "G", + "Х": "H", + "И": "I", + "Й": "Y", + "Я": "Ya", + "Ю": "Yu", + "К": "K", + "Л": "L", + "М": "M", + "Н": "N", + "О": "O", + "П": "P", + "Р": "R", + "С": "S", + "Ш": "Sh", + "Щ": "Shch", + "Т": "T", + "У": "U", + "В": "V", + "Ы": "Y", + "З": "Z", + "Ж": "Zh", + "ъ": "", + "ь": "", + "а": "a", + "б": "b", + "ц": "c", + "ч": "ch", + "д": "d", + "е": "e", + "ё": "e", + "э": "e", + "ф": "f", + "г": "g", + "х": "h", + "и": "i", + "й": "y", + "я": "ya", + "ю": "yu", + "к": "k", + "л": "l", + "м": "m", + "н": "n", + "о": "o", + "п": "p", + "р": "r", + "с": "s", + "ш": "sh", + "щ": "shch", + "т": "t", + "у": "u", + "в": "v", + "ы": "y", + "з": "z", + "ж": "zh" +} diff --git a/Resources/rules/swedish.json b/Resources/rules/swedish.json new file mode 100644 index 00000000..90960493 --- /dev/null +++ b/Resources/rules/swedish.json @@ -0,0 +1,6 @@ +{ + "Ä": "A", + "Ö": "O", + "ä": "a", + "ö": "ö" +} diff --git a/Resources/rules/turkish.json b/Resources/rules/turkish.json new file mode 100644 index 00000000..07fbae50 --- /dev/null +++ b/Resources/rules/turkish.json @@ -0,0 +1,14 @@ +{ + "Ç": "C", + "Ğ": "G", + "İ": "I", + "Ş": "S", + "Ö": "O", + "Ü": "U", + "ç": "c", + "ğ": "g", + "ı": "i", + "ş": "s", + "ö": "o", + "ü": "u" +} diff --git a/Resources/rules/ukrainian.json b/Resources/rules/ukrainian.json new file mode 100644 index 00000000..673b7eda --- /dev/null +++ b/Resources/rules/ukrainian.json @@ -0,0 +1,10 @@ +{ + "Ґ": "G", + "І": "I", + "Ї": "Ji", + "Є": "Ye", + "ґ": "g", + "і": "i", + "ї": "ji", + "є": "ye" +} diff --git a/Resources/rules/vietnamese.json b/Resources/rules/vietnamese.json new file mode 100644 index 00000000..569298b8 --- /dev/null +++ b/Resources/rules/vietnamese.json @@ -0,0 +1,92 @@ +{ + "ạ": "a", + "ả": "a", + "ầ": "a", + "ấ": "a", + "ậ": "a", + "ẩ": "a", + "ẫ": "a", + "ằ": "a", + "ắ": "a", + "ặ": "a", + "ẳ": "a", + "ẵ": "a", + "ẹ": "e", + "ẻ": "e", + "ẽ": "e", + "ề": "e", + "ế": "e", + "ệ": "e", + "ể": "e", + "ễ": "e", + "ị": "i", + "ỉ": "i", + "ọ": "o", + "ỏ": "o", + "ồ": "o", + "ố": "o", + "ộ": "o", + "ổ": "o", + "ỗ": "o", + "ờ": "o", + "ớ": "o", + "ợ": "o", + "ở": "o", + "ỡ": "o", + "ụ": "u", + "ủ": "u", + "ừ": "u", + "ứ": "u", + "ự": "u", + "ử": "u", + "ữ": "u", + "ỳ": "y", + "ỵ": "y", + "ỷ": "y", + "ỹ": "y", + "Ạ": "A", + "Ả": "A", + "Ầ": "A", + "Ấ": "A", + "Ậ": "A", + "Ẩ": "A", + "Ẫ": "A", + "Ằ": "A", + "Ắ": "A", + "Ặ": "A", + "Ẳ": "A", + "Ẵ": "A", + "Ẹ": "E", + "Ẻ": "E", + "Ẽ": "E", + "Ề": "E", + "Ế": "E", + "Ệ": "E", + "Ể": "E", + "Ễ": "E", + "Ị": "I", + "Ỉ": "I", + "Ọ": "O", + "Ỏ": "O", + "Ồ": "O", + "Ố": "O", + "Ộ": "O", + "Ổ": "O", + "Ỗ": "O", + "Ờ": "O", + "Ớ": "O", + "Ợ": "O", + "Ở": "O", + "Ỡ": "O", + "Ụ": "U", + "Ủ": "U", + "Ừ": "U", + "Ứ": "U", + "Ự": "U", + "Ử": "U", + "Ữ": "U", + "Ỳ": "Y", + "Ỵ": "Y", + "Ỷ": "Y", + "Ỹ": "Y" +} diff --git a/bin/generate-default.php b/bin/generate-default.php new file mode 100644 index 00000000..c3caa929 --- /dev/null +++ b/bin/generate-default.php @@ -0,0 +1,58 @@ +isFile() && $file->getExtension() === 'json') { + $rules[$file->getBasename('.json')] = json_decode(file_get_contents($file->getRealPath()), true); + } + } + + return $rules; +} + +/** + * @param string $fileName + * @param array $rules + * + * @return bool + */ +function insertRules($fileName, array $rules = []) +{ + $startTag = '/*INSERT_START*/'; + $endTag = '/*INSERT_END*/'; + + $content = file_get_contents($fileName); + $content = preg_replace( + $regexp = sprintf('#%s(.*)%s#', quotemeta($startTag), quotemeta($endTag)), + $startTag.var_export($rules, true).$endTag, + $content + ); + + return false !== file_put_contents($fileName, $content); +} + +$directory = __DIR__.'/../Resources/rules'; +$fileName = __DIR__.'/../src/RuleProvider/DefaultRuleProvider.php'; +$rules = getRules($directory); + +$result = insertRules($fileName, $rules); + +$ruleCount = array_reduce($rules, function ($count, $rules) { + return $count + count($rules); +}, 0); + +if ($result) { + printf("Written %d rules into '%s'.\n", $ruleCount, $fileName); +} else { + printf("Error writing rules into '%s'.\n", $fileName); +} + diff --git a/composer.json b/composer.json index ee418f95..62d13bc2 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "require-dev": { "phpunit/phpunit": "~4.8", "mockery/mockery": "~0.9", - "satooshi/php-coveralls": "0.6.*", + "mikey179/vfsStream": "~1.6", "symfony/http-kernel": "~2.4", "symfony/dependency-injection": "~2.4", "twig/twig": "~1", @@ -29,7 +29,6 @@ "zendframework/zend-modulemanager": "~2.2", "zendframework/zend-view": "~2.2", "zendframework/zend-servicemanager": "~2.2", - "codeclimate/php-test-reporter": "dev-master", "laravel/framework": "~5.1", "nette/di": "~2.2", "latte/latte": "~2.2", diff --git a/humbug.json.dist b/humbug.json.dist deleted file mode 100644 index 412f220a..00000000 --- a/humbug.json.dist +++ /dev/null @@ -1,11 +0,0 @@ -{ - "source": { - "directories": [ - "src" - ] - }, - "timeout": 10, - "logs": { - "text": "humbuglog.txt" - } -} \ No newline at end of file diff --git a/phpunit.xml.dist b/phpunit.xml.dist index da3734ed..3b7a1d1f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -13,7 +13,7 @@ - - - + + + diff --git a/src/Bridge/Latte/SlugifyHelper.php b/src/Bridge/Latte/SlugifyHelper.php index 6fc5456e..0be9df07 100644 --- a/src/Bridge/Latte/SlugifyHelper.php +++ b/src/Bridge/Latte/SlugifyHelper.php @@ -17,17 +17,17 @@ class SlugifyHelper /** @var SlugifyInterface */ private $slugify; - /** - * @codeCoverageIgnore - */ + /** + * @codeCoverageIgnore + */ public function __construct(SlugifyInterface $slugify) { $this->slugify = $slugify; } /** - * @param string - * @param string + * @param string $string + * @param string $separator * * @return string */ diff --git a/src/Bridge/Silex/SlugifyServiceProvider.php b/src/Bridge/Silex/SlugifyServiceProvider.php index 6a612785..058a7517 100644 --- a/src/Bridge/Silex/SlugifyServiceProvider.php +++ b/src/Bridge/Silex/SlugifyServiceProvider.php @@ -32,11 +32,11 @@ class SlugifyServiceProvider implements ServiceProviderInterface */ public function register(Application $app) { - $app['slugify.regex'] = null; - $app['slugify.options'] = array(); + $app['slugify.options'] = []; + $app['slugify.provider'] = null; $app['slugify'] = $app->share(function ($app) { - return new Slugify($app['slugify.regex'], $app['slugify.options']); + return new Slugify($app['slugify.options'], $app['slugify.provider']); }); if (isset($app['twig'])) { diff --git a/src/Bridge/Symfony/CocurSlugifyExtension.php b/src/Bridge/Symfony/CocurSlugifyExtension.php index e7fcfe32..d92fc6c2 100644 --- a/src/Bridge/Symfony/CocurSlugifyExtension.php +++ b/src/Bridge/Symfony/CocurSlugifyExtension.php @@ -41,7 +41,7 @@ public function load(array $configs, ContainerBuilder $container) 'cocur_slugify.twig.slugify', new Definition( 'Cocur\Slugify\Bridge\Twig\SlugifyExtension', - array(new Reference('cocur_slugify')) + [new Reference('cocur_slugify')] ) ) ->addTag('twig.extension') diff --git a/src/Bridge/Twig/SlugifyExtension.php b/src/Bridge/Twig/SlugifyExtension.php index 04e1b697..1c71e586 100644 --- a/src/Bridge/Twig/SlugifyExtension.php +++ b/src/Bridge/Twig/SlugifyExtension.php @@ -12,6 +12,7 @@ namespace Cocur\Slugify\Bridge\Twig; use Cocur\Slugify\SlugifyInterface; +use Twig_SimpleFilter; /** * SlugifyExtension @@ -19,12 +20,14 @@ * @package cocur/slugify * @subpackage bridge * @author Florian Eckerstorfer - * @copyright 2012-2014 Florian Eckerstorfer + * @copyright 2012-2015 Florian Eckerstorfer * @license http://www.opensource.org/licenses/MIT The MIT License */ class SlugifyExtension extends \Twig_Extension { - /** @var SlugifyInterface */ + /** + * @var SlugifyInterface + */ private $slugify; /** @@ -42,12 +45,12 @@ public function __construct(SlugifyInterface $slugify) /** * Returns the Twig functions of this extension. * - * @return \Twig_SimpleFilter[] + * @return Twig_SimpleFilter[] */ public function getFilters() { return array( - new \Twig_SimpleFilter('slugify', array($this, 'slugifyFilter')), + new Twig_SimpleFilter('slugify', [$this, 'slugifyFilter']), ); } diff --git a/src/Bridge/ZF2/Module.php b/src/Bridge/ZF2/Module.php index dce218af..74e2ec87 100644 --- a/src/Bridge/ZF2/Module.php +++ b/src/Bridge/ZF2/Module.php @@ -23,14 +23,14 @@ class Module implements ServiceProviderInterface, ViewHelperProviderInterface */ public function getServiceConfig() { - return array( - 'factories' => array( + return [ + 'factories' => [ 'Cocur\Slugify\Slugify' => 'Cocur\Slugify\Bridge\ZF2\SlugifyService' - ), - 'aliases' => array( + ], + 'aliases' => [ 'slugify' => 'Cocur\Slugify\Slugify' - ) - ); + ] + ]; } /** @@ -41,10 +41,10 @@ public function getServiceConfig() */ public function getViewHelperConfig() { - return array( - 'factories' => array( + return [ + 'factories' => [ 'slugify' => 'Cocur\Slugify\Bridge\ZF2\SlugifyViewHelperFactory' - ) - ); + ] + ]; } } diff --git a/src/Bridge/ZF2/SlugifyService.php b/src/Bridge/ZF2/SlugifyService.php index fd70e675..44686b8d 100644 --- a/src/Bridge/ZF2/SlugifyService.php +++ b/src/Bridge/ZF2/SlugifyService.php @@ -22,10 +22,9 @@ public function __invoke($sm) { $config = $sm->get('Config'); - if (isset($config[Module::CONFIG_KEY]['reg_exp'])) { - return new Slugify($config[Module::CONFIG_KEY]['reg_exp']); - } else { - return new Slugify(); - } + $options = isset($config[Module::CONFIG_KEY]['options']) ? $config[Module::CONFIG_KEY]['options'] : []; + $provider = isset($config[Module::CONFIG_KEY]['provider']) ? $config[Module::CONFIG_KEY]['provider'] : null; + + return new Slugify($options, $provider); } } diff --git a/src/Bridge/ZF2/SlugifyViewHelperFactory.php b/src/Bridge/ZF2/SlugifyViewHelperFactory.php index 90f71d66..1929234d 100644 --- a/src/Bridge/ZF2/SlugifyViewHelperFactory.php +++ b/src/Bridge/ZF2/SlugifyViewHelperFactory.php @@ -22,6 +22,7 @@ public function __invoke($vhm) { /** @var Slugify $slugify */ $slugify = $vhm->getServiceLocator()->get('Cocur\Slugify\Slugify'); + return new SlugifyViewHelper($slugify); } } diff --git a/src/RuleProvider/DefaultRuleProvider.php b/src/RuleProvider/DefaultRuleProvider.php new file mode 100644 index 00000000..77f7948c --- /dev/null +++ b/src/RuleProvider/DefaultRuleProvider.php @@ -0,0 +1,797 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Cocur\Slugify\RuleProvider; + +/** + * DefaultRuleProvider + * + * @package Cocur\Slugify\RuleProvider + * @author Florian Eckerstorfer + * @copyright 2015 Florian Eckerstorfer + */ +class DefaultRuleProvider implements RuleProviderInterface +{ + /** + * DO NOT MODIFY THESE RULES! + * These rules are generated by the script in bin/generate-rules.php based on the JSON files + * in Resources/rules. + * + * @var array + */ + protected $rules = /*INSERT_START*/[ + 'arabic' => [ + 'أ' => 'a', + 'ب' => 'b', + 'ت' => 't', + 'ث' => 'th', + 'ج' => 'g', + 'ح' => 'h', + 'خ' => 'kh', + 'د' => 'd', + 'ذ' => 'th', + 'ر' => 'r', + 'ز' => 'z', + 'س' => 's', + 'ش' => 'sh', + 'ص' => 's', + 'ض' => 'd', + 'ط' => 't', + 'ظ' => 'th', + 'ع' => 'aa', + 'غ' => 'gh', + 'ف' => 'f', + 'ق' => 'k', + 'ك' => 'k', + 'ل' => 'l', + 'م' => 'm', + 'ن' => 'n', + 'ه' => 'h', + 'و' => 'o', + 'ي' => 'y', + ], + 'austrian' => [ + 'Ä' => 'AE', + 'Ö' => 'OE', + 'Ü' => 'UE', + 'ß' => 'sz', + 'ä' => 'ae', + 'ö' => 'oe', + 'ü' => 'ue', + ], + 'burmese' => [ + 'က' => 'k', + 'ခ' => 'kh', + 'ဂ' => 'g', + 'ဃ' => 'ga', + 'င' => 'ng', + 'စ' => 's', + 'ဆ' => 'sa', + 'ဇ' => 'z', + 'စျ' => 'za', + 'ည' => 'ny', + 'ဋ' => 't', + 'ဌ' => 'ta', + 'ဍ' => 'd', + 'ဎ' => 'da', + 'ဏ' => 'na', + 'တ' => 't', + 'ထ' => 'ta', + 'ဒ' => 'd', + 'ဓ' => 'da', + 'န' => 'n', + 'ပ' => 'p', + 'ဖ' => 'pa', + 'ဗ' => 'b', + 'ဘ' => 'ba', + 'မ' => 'm', + 'ယ' => 'y', + 'ရ' => 'ya', + 'လ' => 'l', + 'ဝ' => 'w', + 'သ' => 'th', + 'ဟ' => 'h', + 'ဠ' => 'la', + 'အ' => 'a', + 'ြ' => 'y', + 'ျ' => 'ya', + 'ွ' => 'w', + 'ြွ' => 'yw', + 'ျွ' => 'ywa', + 'ှ' => 'h', + 'ဧ' => 'e', + '၏' => '-e', + 'ဣ' => 'i', + 'ဤ' => '-i', + 'ဉ' => 'u', + 'ဦ' => '-u', + 'ဩ' => 'aw', + 'သြော' => 'aw', + 'ဪ' => 'aw', + '၍' => 'ywae', + '၌' => 'hnaik', + '၀' => '0', + '၁' => '1', + '၂' => '2', + '၃' => '3', + '၄' => '4', + '၅' => '5', + '၆' => '6', + '၇' => '7', + '၈' => '8', + '၉' => '9', + '္' => '', + '့' => '', + 'း' => '', + 'ာ' => 'a', + 'ါ' => 'a', + 'ေ' => 'e', + 'ဲ' => 'e', + 'ိ' => 'i', + 'ီ' => 'i', + 'ို' => 'o', + 'ု' => 'u', + 'ူ' => 'u', + 'ေါင်' => 'aung', + 'ော' => 'aw', + 'ော်' => 'aw', + 'ေါ' => 'aw', + 'ေါ်' => 'aw', + '်' => 'at', + 'က်' => 'et', + 'ိုက်' => 'aik', + 'ောက်' => 'auk', + 'င်' => 'in', + 'ိုင်' => 'aing', + 'ောင်' => 'aung', + 'စ်' => 'it', + 'ည်' => 'i', + 'တ်' => 'at', + 'ိတ်' => 'eik', + 'ုတ်' => 'ok', + 'ွတ်' => 'ut', + 'ေတ်' => 'it', + 'ဒ်' => 'd', + 'ိုဒ်' => 'ok', + 'ုဒ်' => 'ait', + 'န်' => 'an', + 'ာန်' => 'an', + 'ိန်' => 'ein', + 'ုန်' => 'on', + 'ွန်' => 'un', + 'ပ်' => 'at', + 'ိပ်' => 'eik', + 'ုပ်' => 'ok', + 'ွပ်' => 'ut', + 'န်ုပ်' => 'nub', + 'မ်' => 'an', + 'ိမ်' => 'ein', + 'ုမ်' => 'on', + 'ွမ်' => 'un', + 'ယ်' => 'e', + 'ိုလ်' => 'ol', + 'ဉ်' => 'in', + 'ံ' => 'an', + 'ိံ' => 'ein', + 'ုံ' => 'on', + ], + 'czech' => [ + 'Č' => 'C', + 'Ď' => 'D', + 'Ě' => 'E', + 'Ň' => 'N', + 'Ř' => 'R', + 'Š' => 'S', + 'Ť' => 'T', + 'Ů' => 'U', + 'Ž' => 'Z', + 'č' => 'c', + 'ď' => 'd', + 'ě' => 'e', + 'ň' => 'n', + 'ř' => 'r', + 'š' => 's', + 'ť' => 't', + 'ů' => 'u', + 'ž' => 'z', + ], + 'default' => [ + '°' => '0', + '¹' => '1', + '²' => '2', + '³' => '3', + '⁴' => '4', + '⁵' => '5', + '⁶' => '6', + '⁷' => '7', + '⁸' => '8', + '⁹' => '9', + '₀' => '0', + '₁' => '1', + '₂' => '2', + '₃' => '3', + '₄' => '4', + '₅' => '5', + '₆' => '6', + '₇' => '7', + '₈' => '8', + '₉' => '9', + 'æ' => 'ae', + 'ǽ' => 'ae', + 'À' => 'A', + 'Á' => 'A', + 'Â' => 'A', + 'Ã' => 'A', + 'Å' => 'AA', + 'Ǻ' => 'A', + 'Ă' => 'A', + 'Ǎ' => 'A', + 'Æ' => 'AE', + 'Ǽ' => 'AE', + 'à' => 'a', + 'á' => 'a', + 'â' => 'a', + 'ã' => 'a', + 'å' => 'aa', + 'ǻ' => 'a', + 'ă' => 'a', + 'ǎ' => 'a', + 'ª' => 'a', + '@' => 'at', + 'Ĉ' => 'C', + 'Ċ' => 'C', + 'ĉ' => 'c', + 'ċ' => 'c', + '©' => 'c', + 'Ð' => 'Dj', + 'Đ' => 'D', + 'ð' => 'dj', + 'đ' => 'd', + 'È' => 'E', + 'É' => 'E', + 'Ê' => 'E', + 'Ë' => 'E', + 'Ĕ' => 'E', + 'Ė' => 'E', + 'è' => 'e', + 'é' => 'e', + 'ê' => 'e', + 'ë' => 'e', + 'ĕ' => 'e', + 'ė' => 'e', + 'ƒ' => 'f', + 'Ĝ' => 'G', + 'Ġ' => 'G', + 'ĝ' => 'g', + 'ġ' => 'g', + 'Ĥ' => 'H', + 'Ħ' => 'H', + 'ĥ' => 'h', + 'ħ' => 'h', + 'Ì' => 'I', + 'Í' => 'I', + 'Î' => 'I', + 'Ï' => 'I', + 'Ĩ' => 'I', + 'Ĭ' => 'I', + 'Ǐ' => 'I', + 'Į' => 'I', + 'IJ' => 'IJ', + 'ì' => 'i', + 'í' => 'i', + 'î' => 'i', + 'ï' => 'i', + 'ĩ' => 'i', + 'ĭ' => 'i', + 'ǐ' => 'i', + 'į' => 'i', + 'ij' => 'ij', + 'Ĵ' => 'J', + 'ĵ' => 'j', + 'Ĺ' => 'L', + 'Ľ' => 'L', + 'Ŀ' => 'L', + 'ĺ' => 'l', + 'ľ' => 'l', + 'ŀ' => 'l', + 'Ñ' => 'N', + 'ñ' => 'n', + 'ʼn' => 'n', + 'Ò' => 'O', + 'Ô' => 'O', + 'Õ' => 'O', + 'Ō' => 'O', + 'Ŏ' => 'O', + 'Ǒ' => 'O', + 'Ő' => 'O', + 'Ơ' => 'O', + 'Ø' => 'OE', + 'Ǿ' => 'O', + 'Œ' => 'OE', + 'ò' => 'o', + 'ô' => 'o', + 'õ' => 'o', + 'ō' => 'o', + 'ŏ' => 'o', + 'ǒ' => 'o', + 'ő' => 'o', + 'ơ' => 'o', + 'ø' => 'oe', + 'ǿ' => 'o', + 'º' => 'o', + 'œ' => 'oe', + 'Ŕ' => 'R', + 'Ŗ' => 'R', + 'ŕ' => 'r', + 'ŗ' => 'r', + 'Ŝ' => 'S', + 'Ș' => 'S', + 'ŝ' => 's', + 'ș' => 's', + 'ſ' => 's', + 'Ţ' => 'T', + 'Ț' => 'T', + 'Ŧ' => 'T', + 'Þ' => 'TH', + 'ţ' => 't', + 'ț' => 't', + 'ŧ' => 't', + 'þ' => 'th', + 'Ù' => 'U', + 'Ú' => 'U', + 'Û' => 'U', + 'Ũ' => 'U', + 'Ŭ' => 'U', + 'Ű' => 'U', + 'Ų' => 'U', + 'Ư' => 'U', + 'Ǔ' => 'U', + 'Ǖ' => 'U', + 'Ǘ' => 'U', + 'Ǚ' => 'U', + 'Ǜ' => 'U', + 'ù' => 'u', + 'ú' => 'u', + 'û' => 'u', + 'ũ' => 'u', + 'ŭ' => 'u', + 'ű' => 'u', + 'ų' => 'u', + 'ư' => 'u', + 'ǔ' => 'u', + 'ǖ' => 'u', + 'ǘ' => 'u', + 'ǚ' => 'u', + 'ǜ' => 'u', + 'Ŵ' => 'W', + 'ŵ' => 'w', + 'Ý' => 'Y', + 'Ÿ' => 'Y', + 'Ŷ' => 'Y', + 'ý' => 'y', + 'ÿ' => 'y', + 'ŷ' => 'y', + ], + 'esperanto' => [ + 'ĉ' => 'cx', + 'ĝ' => 'gx', + 'ĥ' => 'hx', + 'ĵ' => 'jx', + 'ŝ' => 'sx', + 'ŭ' => 'ux', + 'Ĉ' => 'CX', + 'Ĝ' => 'GX', + 'Ĥ' => 'HX', + 'Ĵ' => 'JX', + 'Ŝ' => 'SX', + 'Ŭ' => 'UX', + ], + 'finnish' => [ + 'Ä' => 'A', + 'Ö' => 'O', + 'ä' => 'a', + 'ö' => 'o', + ], + 'georgian' => [ + 'ა' => 'a', + 'ბ' => 'b', + 'გ' => 'g', + 'დ' => 'd', + 'ე' => 'e', + 'ვ' => 'v', + 'ზ' => 'z', + 'თ' => 't', + 'ი' => 'i', + 'კ' => 'k', + 'ლ' => 'l', + 'მ' => 'm', + 'ნ' => 'n', + 'ო' => 'o', + 'პ' => 'p', + 'ჟ' => 'zh', + 'რ' => 'r', + 'ს' => 's', + 'ტ' => 't', + 'უ' => 'u', + 'ფ' => 'f', + 'ქ' => 'k', + 'ღ' => 'gh', + 'ყ' => 'q', + 'შ' => 'sh', + 'ჩ' => 'ch', + 'ც' => 'ts', + 'ძ' => 'dz', + 'წ' => 'ts', + 'ჭ' => 'ch', + 'ხ' => 'kh', + 'ჯ' => 'j', + 'ჰ' => 'h', + ], + 'german' => [ + 'Ä' => 'AE', + 'Ö' => 'OE', + 'Ü' => 'UE', + 'ß' => 'ss', + 'ä' => 'ae', + 'ö' => 'oe', + 'ü' => 'ue', + ], + 'greek' => [ + 'ΑΥ' => 'AU', + 'Αυ' => 'Au', + 'ΟΥ' => 'OU', + 'Ου' => 'Ou', + 'ΕΥ' => 'EU', + 'Ευ' => 'Eu', + 'ΕΙ' => 'I', + 'Ει' => 'I', + 'ΟΙ' => 'I', + 'Οι' => 'I', + 'ΥΙ' => 'I', + 'Υι' => 'I', + 'ΑΎ' => 'AU', + 'Αύ' => 'Au', + 'ΟΎ' => 'OU', + 'Ού' => 'Ou', + 'ΕΎ' => 'EU', + 'Εύ' => 'Eu', + 'ΕΊ' => 'I', + 'Εί' => 'I', + 'ΟΊ' => 'I', + 'Οί' => 'I', + 'ΎΙ' => 'I', + 'Ύι' => 'I', + 'ΥΊ' => 'I', + 'Υί' => 'I', + 'αυ' => 'au', + 'ου' => 'ou', + 'ευ' => 'eu', + 'ει' => 'i', + 'οι' => 'i', + 'υι' => 'i', + 'αύ' => 'au', + 'ού' => 'ou', + 'εύ' => 'eu', + 'εί' => 'i', + 'οί' => 'i', + 'ύι' => 'i', + 'υί' => 'i', + 'Α' => 'A', + 'Β' => 'V', + 'Γ' => 'G', + 'Δ' => 'D', + 'Ε' => 'E', + 'Ζ' => 'Z', + 'Η' => 'I', + 'Θ' => 'Th', + 'Ι' => 'I', + 'Κ' => 'K', + 'Λ' => 'L', + 'Μ' => 'M', + 'Ν' => 'N', + 'Ξ' => 'X', + 'Ο' => 'O', + 'Π' => 'P', + 'Ρ' => 'R', + 'Σ' => 'S', + 'Τ' => 'T', + 'Υ' => 'I', + 'Φ' => 'F', + 'Χ' => 'Ch', + 'Ψ' => 'Ps', + 'Ω' => 'O', + 'Ά' => 'A', + 'Έ' => 'E', + 'Ή' => 'I', + 'Ί' => 'I', + 'Ό' => 'O', + 'Ύ' => 'I', + 'Ϊ' => 'I', + 'Ϋ' => 'I', + 'ϒ' => 'I', + 'α' => 'a', + 'β' => 'v', + 'γ' => 'g', + 'δ' => 'd', + 'ε' => 'e', + 'ζ' => 'z', + 'η' => 'i', + 'θ' => 'th', + 'ι' => 'i', + 'κ' => 'k', + 'λ' => 'l', + 'μ' => 'm', + 'ν' => 'n', + 'ξ' => 'x', + 'ο' => 'o', + 'π' => 'p', + 'ρ' => 'r', + 'ς' => 's', + 'σ' => 's', + 'τ' => 't', + 'υ' => 'i', + 'φ' => 'f', + 'χ' => 'ch', + 'ψ' => 'ps', + 'ω' => 'o', + 'ά' => 'a', + 'έ' => 'e', + 'ή' => 'i', + 'ί' => 'i', + 'ό' => 'o', + 'ύ' => 'i', + 'ϊ' => 'i', + 'ϋ' => 'i', + 'ΰ' => 'i', + 'ώ' => 'o', + 'ϐ' => 'v', + 'ϑ' => 'th', + ], + 'latvian' => [ + 'Ā' => 'A', + 'Ē' => 'E', + 'Ģ' => 'G', + 'Ī' => 'I', + 'Ķ' => 'K', + 'Ļ' => 'L', + 'Ņ' => 'N', + 'Ū' => 'U', + 'ā' => 'a', + 'ē' => 'e', + 'ģ' => 'g', + 'ī' => 'i', + 'ķ' => 'k', + 'ļ' => 'l', + 'ņ' => 'n', + 'ū' => 'u', + ], + 'polish' => [ + 'Ą' => 'A', + 'Ć' => 'C', + 'Ę' => 'E', + 'Ł' => 'L', + 'Ń' => 'N', + 'Ó' => 'O', + 'Ś' => 'S', + 'Ź' => 'Z', + 'Ż' => 'Z', + 'ą' => 'a', + 'ć' => 'c', + 'ę' => 'e', + 'ł' => 'l', + 'ń' => 'n', + 'ó' => 'o', + 'ś' => 's', + 'ź' => 'z', + 'ż' => 'z', + ], + 'russian' => [ + 'Ъ' => '', + 'Ь' => '', + 'А' => 'A', + 'Б' => 'B', + 'Ц' => 'C', + 'Ч' => 'Ch', + 'Д' => 'D', + 'Е' => 'E', + 'Ё' => 'E', + 'Э' => 'E', + 'Ф' => 'F', + 'Г' => 'G', + 'Х' => 'H', + 'И' => 'I', + 'Й' => 'Y', + 'Я' => 'Ya', + 'Ю' => 'Yu', + 'К' => 'K', + 'Л' => 'L', + 'М' => 'M', + 'Н' => 'N', + 'О' => 'O', + 'П' => 'P', + 'Р' => 'R', + 'С' => 'S', + 'Ш' => 'Sh', + 'Щ' => 'Shch', + 'Т' => 'T', + 'У' => 'U', + 'В' => 'V', + 'Ы' => 'Y', + 'З' => 'Z', + 'Ж' => 'Zh', + 'ъ' => '', + 'ь' => '', + 'а' => 'a', + 'б' => 'b', + 'ц' => 'c', + 'ч' => 'ch', + 'д' => 'd', + 'е' => 'e', + 'ё' => 'e', + 'э' => 'e', + 'ф' => 'f', + 'г' => 'g', + 'х' => 'h', + 'и' => 'i', + 'й' => 'y', + 'я' => 'ya', + 'ю' => 'yu', + 'к' => 'k', + 'л' => 'l', + 'м' => 'm', + 'н' => 'n', + 'о' => 'o', + 'п' => 'p', + 'р' => 'r', + 'с' => 's', + 'ш' => 'sh', + 'щ' => 'shch', + 'т' => 't', + 'у' => 'u', + 'в' => 'v', + 'ы' => 'y', + 'з' => 'z', + 'ж' => 'zh', + ], + 'swedish' => [ + 'Ä' => 'A', + 'Ö' => 'O', + 'ä' => 'a', + 'ö' => 'ö', + ], + 'turkish' => [ + 'Ç' => 'C', + 'Ğ' => 'G', + 'İ' => 'I', + 'Ş' => 'S', + 'Ö' => 'O', + 'Ü' => 'U', + 'ç' => 'c', + 'ğ' => 'g', + 'ı' => 'i', + 'ş' => 's', + 'ö' => 'o', + 'ü' => 'u', + ], + 'ukrainian' => [ + 'Ґ' => 'G', + 'І' => 'I', + 'Ї' => 'Ji', + 'Є' => 'Ye', + 'ґ' => 'g', + 'і' => 'i', + 'ї' => 'ji', + 'є' => 'ye', + ], + 'vietnamese' => [ + 'ạ' => 'a', + 'ả' => 'a', + 'ầ' => 'a', + 'ấ' => 'a', + 'ậ' => 'a', + 'ẩ' => 'a', + 'ẫ' => 'a', + 'ằ' => 'a', + 'ắ' => 'a', + 'ặ' => 'a', + 'ẳ' => 'a', + 'ẵ' => 'a', + 'ẹ' => 'e', + 'ẻ' => 'e', + 'ẽ' => 'e', + 'ề' => 'e', + 'ế' => 'e', + 'ệ' => 'e', + 'ể' => 'e', + 'ễ' => 'e', + 'ị' => 'i', + 'ỉ' => 'i', + 'ọ' => 'o', + 'ỏ' => 'o', + 'ồ' => 'o', + 'ố' => 'o', + 'ộ' => 'o', + 'ổ' => 'o', + 'ỗ' => 'o', + 'ờ' => 'o', + 'ớ' => 'o', + 'ợ' => 'o', + 'ở' => 'o', + 'ỡ' => 'o', + 'ụ' => 'u', + 'ủ' => 'u', + 'ừ' => 'u', + 'ứ' => 'u', + 'ự' => 'u', + 'ử' => 'u', + 'ữ' => 'u', + 'ỳ' => 'y', + 'ỵ' => 'y', + 'ỷ' => 'y', + 'ỹ' => 'y', + 'Ạ' => 'A', + 'Ả' => 'A', + 'Ầ' => 'A', + 'Ấ' => 'A', + 'Ậ' => 'A', + 'Ẩ' => 'A', + 'Ẫ' => 'A', + 'Ằ' => 'A', + 'Ắ' => 'A', + 'Ặ' => 'A', + 'Ẳ' => 'A', + 'Ẵ' => 'A', + 'Ẹ' => 'E', + 'Ẻ' => 'E', + 'Ẽ' => 'E', + 'Ề' => 'E', + 'Ế' => 'E', + 'Ệ' => 'E', + 'Ể' => 'E', + 'Ễ' => 'E', + 'Ị' => 'I', + 'Ỉ' => 'I', + 'Ọ' => 'O', + 'Ỏ' => 'O', + 'Ồ' => 'O', + 'Ố' => 'O', + 'Ộ' => 'O', + 'Ổ' => 'O', + 'Ỗ' => 'O', + 'Ờ' => 'O', + 'Ớ' => 'O', + 'Ợ' => 'O', + 'Ở' => 'O', + 'Ỡ' => 'O', + 'Ụ' => 'U', + 'Ủ' => 'U', + 'Ừ' => 'U', + 'Ứ' => 'U', + 'Ự' => 'U', + 'Ử' => 'U', + 'Ữ' => 'U', + 'Ỳ' => 'Y', + 'Ỵ' => 'Y', + 'Ỷ' => 'Y', + 'Ỹ' => 'Y', + ], + ]/*INSERT_END*/; + + /** + * @param string $ruleset + * + * @return array + */ + public function getRules($ruleset) + { + return $this->rules[$ruleset]; + } +} diff --git a/src/RuleProvider/FileRuleProvider.php b/src/RuleProvider/FileRuleProvider.php new file mode 100644 index 00000000..60659337 --- /dev/null +++ b/src/RuleProvider/FileRuleProvider.php @@ -0,0 +1,47 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Cocur\Slugify\RuleProvider; + +/** + * FileRuleProvider + * + * @package Cocur\Slugify\RuleProvider + * @author Florian Eckerstorfer + * @copyright 2015 Florian Eckerstorfer + */ +class FileRuleProvider implements RuleProviderInterface +{ + /** + * @var string + */ + protected $directoryName; + + /** + * @param string $directoryName + */ + public function __construct($directoryName) + { + $this->directoryName = $directoryName; + } + + /** + * @param $ruleset + * + * @return array + */ + public function getRules($ruleset) + { + $fileName = $this->directoryName.DIRECTORY_SEPARATOR.$ruleset.'.json'; + + return json_decode(file_get_contents($fileName), true); + } +} diff --git a/src/RuleProvider/RuleProviderInterface.php b/src/RuleProvider/RuleProviderInterface.php new file mode 100644 index 00000000..f5648cc7 --- /dev/null +++ b/src/RuleProvider/RuleProviderInterface.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Cocur\Slugify\RuleProvider; + +/** + * RuleProviderInterface + * + * @package Cocur\Slugify\RuleProvider + * @author Florian Eckerstorfer + * @copyright 2015 Florian Eckerstorfer + */ +interface RuleProviderInterface +{ + /** + * @param $ruleset + * + * @return array + */ + public function getRules($ruleset); +} diff --git a/src/Slugify.php b/src/Slugify.php index 3d21746a..13a4e4b7 100644 --- a/src/Slugify.php +++ b/src/Slugify.php @@ -11,780 +11,73 @@ namespace Cocur\Slugify; +use Cocur\Slugify\RuleProvider\DefaultRuleProvider; +use Cocur\Slugify\RuleProvider\RuleProviderInterface; + /** * Slugify * - * @package org.cocur.slugify + * @package Cocur\Slugify * @author Florian Eckerstorfer * @author Ivo Bathke * @author Marchenko Alexandr - * @copyright 2012-2014 Florian Eckerstorfer + * @copyright 2012-2015 Florian Eckerstorfer * @license http://www.opensource.org/licenses/MIT The MIT License */ class Slugify implements SlugifyInterface { const LOWERCASE_NUMBERS_DASHES = '/([^A-Za-z0-9]|-)+/'; - /** @var array */ - protected $rules = array( - // Numeric characters, superscript - '°' => 0, - '¹' => 1, - '²' => 2, - '³' => 3, - '⁴' => 4, - '⁵' => 5, - '⁶' => 6, - '⁷' => 7, - '⁸' => 8, - '⁹' => 9, - // Numeric characters, subscript - '₀' => 0, - '₁' => 1, - '₂' => 2, - '₃' => 3, - '₄' => 4, - '₅' => 5, - '₆' => 6, - '₇' => 7, - '₈' => 8, - '₉' => 9, - - // Latin - 'æ' => 'ae', - 'ǽ' => 'ae', - 'À' => 'A', - 'Á' => 'A', - 'Â' => 'A', - 'Ã' => 'A', - 'Å' => 'AA', - 'Ǻ' => 'A', - 'Ă' => 'A', - 'Ǎ' => 'A', - 'Æ' => 'AE', - 'Ǽ' => 'AE', - 'à' => 'a', - 'á' => 'a', - 'â' => 'a', - 'ã' => 'a', - 'å' => 'aa', - 'ǻ' => 'a', - 'ă' => 'a', - 'ǎ' => 'a', - 'ª' => 'a', - '@' => 'at', - 'Ĉ' => 'C', - 'Ċ' => 'C', - 'ĉ' => 'c', - 'ċ' => 'c', - '©' => 'c', - 'Ð' => 'Dj', - 'Đ' => 'D', - 'ð' => 'dj', - 'đ' => 'd', - 'È' => 'E', - 'É' => 'E', - 'Ê' => 'E', - 'Ë' => 'E', - 'Ĕ' => 'E', - 'Ė' => 'E', - 'è' => 'e', - 'é' => 'e', - 'ê' => 'e', - 'ë' => 'e', - 'ĕ' => 'e', - 'ė' => 'e', - 'ƒ' => 'f', - 'Ĝ' => 'G', - 'Ġ' => 'G', - 'ĝ' => 'g', - 'ġ' => 'g', - 'Ĥ' => 'H', - 'Ħ' => 'H', - 'ĥ' => 'h', - 'ħ' => 'h', - 'Ì' => 'I', - 'Í' => 'I', - 'Î' => 'I', - 'Ï' => 'I', - 'Ĩ' => 'I', - 'Ĭ' => 'I', - 'Ǐ' => 'I', - 'Į' => 'I', - 'IJ' => 'IJ', - 'ì' => 'i', - 'í' => 'i', - 'î' => 'i', - 'ï' => 'i', - 'ĩ' => 'i', - 'ĭ' => 'i', - 'ǐ' => 'i', - 'į' => 'i', - 'ij' => 'ij', - 'Ĵ' => 'J', - 'ĵ' => 'j', - 'Ĺ' => 'L', - 'Ľ' => 'L', - 'Ŀ' => 'L', - 'ĺ' => 'l', - 'ľ' => 'l', - 'ŀ' => 'l', - 'Ñ' => 'N', - 'ñ' => 'n', - 'ʼn' => 'n', - 'Ò' => 'O', - 'Ô' => 'O', - 'Õ' => 'O', - 'Ō' => 'O', - 'Ŏ' => 'O', - 'Ǒ' => 'O', - 'Ő' => 'O', - 'Ơ' => 'O', - 'Ø' => 'OE', - 'Ǿ' => 'O', - 'Œ' => 'OE', - 'ò' => 'o', - 'ô' => 'o', - 'õ' => 'o', - 'ō' => 'o', - 'ŏ' => 'o', - 'ǒ' => 'o', - 'ő' => 'o', - 'ơ' => 'o', - 'ø' => 'oe', - 'ǿ' => 'o', - 'º' => 'o', - 'œ' => 'oe', - 'Ŕ' => 'R', - 'Ŗ' => 'R', - 'ŕ' => 'r', - 'ŗ' => 'r', - 'Ŝ' => 'S', - 'Ș' => 'S', - 'ŝ' => 's', - 'ș' => 's', - 'ſ' => 's', - 'Ţ' => 'T', - 'Ț' => 'T', - 'Ŧ' => 'T', - 'Þ' => 'TH', - 'ţ' => 't', - 'ț' => 't', - 'ŧ' => 't', - 'þ' => 'th', - 'Ù' => 'U', - 'Ú' => 'U', - 'Û' => 'U', - 'Ũ' => 'U', - 'Ŭ' => 'U', - 'Ű' => 'U', - 'Ų' => 'U', - 'Ư' => 'U', - 'Ǔ' => 'U', - 'Ǖ' => 'U', - 'Ǘ' => 'U', - 'Ǚ' => 'U', - 'Ǜ' => 'U', - 'ù' => 'u', - 'ú' => 'u', - 'û' => 'u', - 'ũ' => 'u', - 'ŭ' => 'u', - 'ű' => 'u', - 'ų' => 'u', - 'ư' => 'u', - 'ǔ' => 'u', - 'ǖ' => 'u', - 'ǘ' => 'u', - 'ǚ' => 'u', - 'ǜ' => 'u', - 'Ŵ' => 'W', - 'ŵ' => 'w', - 'Ý' => 'Y', - 'Ÿ' => 'Y', - 'Ŷ' => 'Y', - 'ý' => 'y', - 'ÿ' => 'y', - 'ŷ' => 'y', - - // Russian - 'Ъ' => '', - 'Ь' => '', - 'А' => 'A', - 'Б' => 'B', - 'Ц' => 'C', - 'Ч' => 'Ch', - 'Д' => 'D', - 'Е' => 'E', - 'Ё' => 'E', - 'Э' => 'E', - 'Ф' => 'F', - 'Г' => 'G', - 'Х' => 'H', - 'И' => 'I', - 'Й' => 'Y', - 'Я' => 'Ya', - 'Ю' => 'Yu', - 'К' => 'K', - 'Л' => 'L', - 'М' => 'M', - 'Н' => 'N', - 'О' => 'O', - 'П' => 'P', - 'Р' => 'R', - 'С' => 'S', - 'Ш' => 'Sh', - 'Щ' => 'Shch', - 'Т' => 'T', - 'У' => 'U', - 'В' => 'V', - 'Ы' => 'Y', - 'З' => 'Z', - 'Ж' => 'Zh', - 'ъ' => '', - 'ь' => '', - 'а' => 'a', - 'б' => 'b', - 'ц' => 'c', - 'ч' => 'ch', - 'д' => 'd', - 'е' => 'e', - 'ё' => 'e', - 'э' => 'e', - 'ф' => 'f', - 'г' => 'g', - 'х' => 'h', - 'и' => 'i', - 'й' => 'y', - 'я' => 'ya', - 'ю' => 'yu', - 'к' => 'k', - 'л' => 'l', - 'м' => 'm', - 'н' => 'n', - 'о' => 'o', - 'п' => 'p', - 'р' => 'r', - 'с' => 's', - 'ш' => 'sh', - 'щ' => 'shch', - 'т' => 't', - 'у' => 'u', - 'в' => 'v', - 'ы' => 'y', - 'з' => 'z', - 'ж' => 'zh', - - // German characters - 'Ä' => 'AE', - 'Ö' => 'OE', - 'Ü' => 'UE', - 'ß' => 'ss', - 'ä' => 'ae', - 'ö' => 'oe', - 'ü' => 'ue', - - // Turkish characters - 'Ç' => 'C', - 'Ğ' => 'G', - 'İ' => 'I', - 'Ş' => 'S', - 'ç' => 'c', - 'ğ' => 'g', - 'ı' => 'i', - 'ş' => 's', - - // Latvian - 'Ā' => 'A', - 'Ē' => 'E', - 'Ģ' => 'G', - 'Ī' => 'I', - 'Ķ' => 'K', - 'Ļ' => 'L', - 'Ņ' => 'N', - 'Ū' => 'U', - 'ā' => 'a', - 'ē' => 'e', - 'ģ' => 'g', - 'ī' => 'i', - 'ķ' => 'k', - 'ļ' => 'l', - 'ņ' => 'n', - 'ū' => 'u', - - // Ukrainian - 'Ґ' => 'G', - 'І' => 'I', - 'Ї' => 'Ji', - 'Є' => 'Ye', - 'ґ' => 'g', - 'і' => 'i', - 'ї' => 'ji', - 'є' => 'ye', - - // Czech - 'Č' => 'C', - 'Ď' => 'D', - 'Ě' => 'E', - 'Ň' => 'N', - 'Ř' => 'R', - 'Š' => 'S', - 'Ť' => 'T', - 'Ů' => 'U', - 'Ž' => 'Z', - 'č' => 'c', - 'ď' => 'd', - 'ě' => 'e', - 'ň' => 'n', - 'ř' => 'r', - 'š' => 's', - 'ť' => 't', - 'ů' => 'u', - 'ž' => 'z', - - // Polish - 'Ą' => 'A', - 'Ć' => 'C', - 'Ę' => 'E', - 'Ł' => 'L', - 'Ń' => 'N', - 'Ó' => 'O', - 'Ś' => 'S', - 'Ź' => 'Z', - 'Ż' => 'Z', - 'ą' => 'a', - 'ć' => 'c', - 'ę' => 'e', - 'ł' => 'l', - 'ń' => 'n', - 'ó' => 'o', - 'ś' => 's', - 'ź' => 'z', - 'ż' => 'z', - - // Greek - 'ΑΥ' => 'AU', - 'Αυ' => 'Au', - 'ΟΥ' => 'OU', - 'Ου' => 'Ou', - 'ΕΥ' => 'EU', - 'Ευ' => 'Eu', - 'ΕΙ' => 'I', - 'Ει' => 'I', - 'ΟΙ' => 'I', - 'Οι' => 'I', - 'ΥΙ' => 'I', - 'Υι' => 'I', - 'ΑΎ' => 'AU', - 'Αύ' => 'Au', - 'ΟΎ' => 'OU', - 'Ού' => 'Ou', - 'ΕΎ' => 'EU', - 'Εύ' => 'Eu', - 'ΕΊ' => 'I', - 'Εί' => 'I', - 'ΟΊ' => 'I', - 'Οί' => 'I', - 'ΎΙ' => 'I', - 'Ύι' => 'I', - 'ΥΊ' => 'I', - 'Υί' => 'I', - 'αυ' => 'au', - 'ου' => 'ou', - 'ευ' => 'eu', - 'ει' => 'i', - 'οι' => 'i', - 'υι' => 'i', - 'αύ' => 'au', - 'ού' => 'ou', - 'εύ' => 'eu', - 'εί' => 'i', - 'οί' => 'i', - 'ύι' => 'i', - 'υί' => 'i', - 'Α' => 'A', - 'Β' => 'V', - 'Γ' => 'G', - 'Δ' => 'D', - 'Ε' => 'E', - 'Ζ' => 'Z', - 'Η' => 'I', - 'Θ' => 'Th', - 'Ι' => 'I', - 'Κ' => 'K', - 'Λ' => 'L', - 'Μ' => 'M', - 'Ν' => 'N', - 'Ξ' => 'X', - 'Ο' => 'O', - 'Π' => 'P', - 'Ρ' => 'R', - 'Σ' => 'S', - 'Τ' => 'T', - 'Υ' => 'I', - 'Φ' => 'F', - 'Χ' => 'Ch', - 'Ψ' => 'Ps', - 'Ω' => 'O', - 'Ά' => 'A', - 'Έ' => 'E', - 'Ή' => 'I', - 'Ί' => 'I', - 'Ό' => 'O', - 'Ύ' => 'I', - 'Ϊ' => 'I', - 'Ϋ' => 'I', - 'ϒ' => 'I', - 'α' => 'a', - 'β' => 'v', - 'γ' => 'g', - 'δ' => 'd', - 'ε' => 'e', - 'ζ' => 'z', - 'η' => 'i', - 'θ' => 'th', - 'ι' => 'i', - 'κ' => 'k', - 'λ' => 'l', - 'μ' => 'm', - 'ν' => 'n', - 'ξ' => 'x', - 'ο' => 'o', - 'π' => 'p', - 'ρ' => 'r', - 'ς' => 's', - 'σ' => 's', - 'τ' => 't', - 'υ' => 'i', - 'φ' => 'f', - 'χ' => 'ch', - 'ψ' => 'ps', - 'ω' => 'o', - 'ά' => 'a', - 'έ' => 'e', - 'ή' => 'i', - 'ί' => 'i', - 'ό' => 'o', - 'ύ' => 'i', - 'ϊ' => 'i', - 'ϋ' => 'i', - 'ΰ' => 'i', - 'ώ' => 'o', - 'ϐ' => 'v', - 'ϑ' => 'th', - - /* Arabic */ - 'أ' => 'a', - 'ب' => 'b', - 'ت' => 't', - 'ث' => 'th', - 'ج' => 'g', - 'ح' => 'h', - 'خ' => 'kh', - 'د' => 'd', - 'ذ' => 'th', - 'ر' => 'r', - 'ز' => 'z', - 'س' => 's', - 'ش' => 'sh', - 'ص' => 's', - 'ض' => 'd', - 'ط' => 't', - 'ظ' => 'th', - 'ع' => 'aa', - 'غ' => 'gh', - 'ف' => 'f', - 'ق' => 'k', - 'ك' => 'k', - 'ل' => 'l', - 'م' => 'm', - 'ن' => 'n', - 'ه' => 'h', - 'و' => 'o', - 'ي' => 'y', - - /* Vietnamese */ - 'ạ' => 'a', - 'ả' => 'a', - 'ầ' => 'a', - 'ấ' => 'a', - 'ậ' => 'a', - 'ẩ' => 'a', - 'ẫ' => 'a', - 'ằ' => 'a', - 'ắ' => 'a', - 'ặ' => 'a', - 'ẳ' => 'a', - 'ẵ' => 'a', - 'ẹ' => 'e', - 'ẻ' => 'e', - 'ẽ' => 'e', - 'ề' => 'e', - 'ế' => 'e', - 'ệ' => 'e', - 'ể' => 'e', - 'ễ' => 'e', - 'ị' => 'i', - 'ỉ' => 'i', - 'ọ' => 'o', - 'ỏ' => 'o', - 'ồ' => 'o', - 'ố' => 'o', - 'ộ' => 'o', - 'ổ' => 'o', - 'ỗ' => 'o', - 'ờ' => 'o', - 'ớ' => 'o', - 'ợ' => 'o', - 'ở' => 'o', - 'ỡ' => 'o', - 'ụ' => 'u', - 'ủ' => 'u', - 'ừ' => 'u', - 'ứ' => 'u', - 'ự' => 'u', - 'ử' => 'u', - 'ữ' => 'u', - 'ỳ' => 'y', - 'ỵ' => 'y', - 'ỷ' => 'y', - 'ỹ' => 'y', - 'Ạ' => 'A', - 'Ả' => 'A', - 'Ầ' => 'A', - 'Ấ' => 'A', - 'Ậ' => 'A', - 'Ẩ' => 'A', - 'Ẫ' => 'A', - 'Ằ' => 'A', - 'Ắ' => 'A', - 'Ặ' => 'A', - 'Ẳ' => 'A', - 'Ẵ' => 'A', - 'Ẹ' => 'E', - 'Ẻ' => 'E', - 'Ẽ' => 'E', - 'Ề' => 'E', - 'Ế' => 'E', - 'Ệ' => 'E', - 'Ể' => 'E', - 'Ễ' => 'E', - 'Ị' => 'I', - 'Ỉ' => 'I', - 'Ọ' => 'O', - 'Ỏ' => 'O', - 'Ồ' => 'O', - 'Ố' => 'O', - 'Ộ' => 'O', - 'Ổ' => 'O', - 'Ỗ' => 'O', - 'Ờ' => 'O', - 'Ớ' => 'O', - 'Ợ' => 'O', - 'Ở' => 'O', - 'Ỡ' => 'O', - 'Ụ' => 'U', - 'Ủ' => 'U', - 'Ừ' => 'U', - 'Ứ' => 'U', - 'Ự' => 'U', - 'Ử' => 'U', - 'Ữ' => 'U', - 'Ỳ' => 'Y', - 'Ỵ' => 'Y', - 'Ỷ' => 'Y', - 'Ỹ' => 'Y', - - /* Georgian */ - 'ა' => 'a', - 'ბ' => 'b', - 'გ' => 'g', - 'დ' => 'd', - 'ე' => 'e', - 'ვ' => 'v', - 'ზ' => 'z', - 'თ' => 't', - 'ი' => 'i', - 'კ' => 'k', - 'ლ' => 'l', - 'მ' => 'm', - 'ნ' => 'n', - 'ო' => 'o', - 'პ' => 'p', - 'ჟ' => 'zh', - 'რ' => 'r', - 'ს' => 's', - 'ტ' => 't', - 'უ' => 'u', - 'ფ' => 'f', - 'ქ' => 'k', - 'ღ' => 'gh', - 'ყ' => 'q', - 'შ' => 'sh', - 'ჩ' => 'ch', - 'ც' => 'ts', - 'ძ' => 'dz', - 'წ' => 'ts', - 'ჭ' => 'ch', - 'ხ' => 'kh', - 'ჯ' => 'j', - 'ჰ' => 'h', - - // burmese consonants - 'က' => 'k', - 'ခ' => 'kh', - 'ဂ' => 'g', - 'ဃ' => 'ga', - 'င' => 'ng', - 'စ' => 's', - 'ဆ' => 'sa', - 'ဇ' => 'z', - 'စျ' => 'za', - 'ည' => 'ny', - 'ဋ' => 't', - 'ဌ' => 'ta', - 'ဍ' => 'd', - 'ဎ' => 'da', - 'ဏ' => 'na', - 'တ' => 't', - 'ထ' => 'ta', - 'ဒ' => 'd', - 'ဓ' => 'da', - 'န' => 'n', - 'ပ' => 'p', - 'ဖ' => 'pa', - 'ဗ' => 'b', - 'ဘ' => 'ba', - 'မ' => 'm', - 'ယ' => 'y', - 'ရ' => 'ya', - 'လ' => 'l', - 'ဝ' => 'w', - 'သ' => 'th', - 'ဟ' => 'h', - 'ဠ' => 'la', - 'အ' => 'a', - // consonant character combos - 'ြ' => 'y', - 'ျ' => 'ya', - 'ွ' => 'w', - 'ြွ' => 'yw', - 'ျွ' => 'ywa', - 'ှ' => 'h', - // independent vowels - 'ဧ' => 'e', - '၏' => '-e', - 'ဣ' => 'i', - 'ဤ' => '-i', - 'ဉ' => 'u', - 'ဦ' => '-u', - 'ဩ' => 'aw', - 'သြော' => 'aw', - 'ဪ' => 'aw', - '၍' => 'ywae', - '၌' => 'hnaik', - // numbers - '၀' => '0', - '၁' => '1', - '၂' => '2', - '၃' => '3', - '၄' => '4', - '၅' => '5', - '၆' => '6', - '၇' => '7', - '၈' => '8', - '၉' => '9', - // virama and tone marks which are silent in transliteration - '္' => '', - '့' => '', - 'း' => '', - // dependent vowels - 'ာ' => 'a', - 'ါ' => 'a', - 'ေ' => 'e', - 'ဲ' => 'e', - 'ိ' => 'i', - 'ီ' => 'i', - 'ို' => 'o', - 'ု' => 'u', - 'ူ' => 'u', - 'ေါင်' => 'aung', - 'ော' => 'aw', - 'ော်' => 'aw', - 'ေါ' => 'aw', - 'ေါ်' => 'aw', - '်' => 'at', - 'က်' => 'et', - 'ိုက်' => 'aik', - 'ောက်' => 'auk', - 'င်' => 'in', - 'ိုင်' => 'aing', - 'ောင်' => 'aung', - 'စ်' => 'it', - 'ည်' => 'i', - 'တ်' => 'at', - 'ိတ်' => 'eik', - 'ုတ်' => 'ok', - 'ွတ်' => 'ut', - 'ေတ်' => 'it', - 'ဒ်' => 'd', - 'ိုဒ်' => 'ok', - 'ုဒ်' => 'ait', - 'န်' => 'an', - 'ာန်' => 'an', - 'ိန်' => 'ein', - 'ုန်' => 'on', - 'ွန်' => 'un', - 'ပ်' => 'at', - 'ိပ်' => 'eik', - 'ုပ်' => 'ok', - 'ွပ်' => 'ut', - 'န်ုပ်' => 'nub', - 'မ်' => 'an', - 'ိမ်' => 'ein', - 'ုမ်' => 'on', - 'ွမ်' => 'un', - 'ယ်' => 'e', - 'ိုလ်' => 'ol', - 'ဉ်' => 'in', - 'ံ' => 'an', - 'ိံ' => 'ein', - 'ုံ' => 'on' - ); - - /** @var array[] */ - protected $rulesets = array( - 'esperanto' => array( - 'ĉ' => 'cx', - 'ĝ' => 'gx', - 'ĥ' => 'hx', - 'ĵ' => 'jx', - 'ŝ' => 'sx', - 'ŭ' => 'ux', - 'Ĉ' => 'CX', - 'Ĝ' => 'GX', - 'Ĥ' => 'HX', - 'Ĵ' => 'JX', - 'Ŝ' => 'SX', - 'Ŭ' => 'UX' - ) - ); + /** + * @var array + */ + protected $rules = []; - /** @var string */ - protected $regExp; + /** + * @var RuleProviderInterface + */ + protected $provider; - /** @var array */ - protected $options = array('lowercase' => true); + /** + * @var array + */ + protected $options = [ + 'regexp' => self::LOWERCASE_NUMBERS_DASHES, + 'lowercase' => true, + 'rulesets' => [ + 'default', + // Languages are preferred if they appear later, list is ordered by number of + // websites in that language + // https://en.wikipedia.org/wiki/Languages_used_on_the_Internet#Content_languages_for_websites + 'burmese', + 'georgian', + 'vietnamese', + 'ukrainian', + 'latvian', + 'finnish', + 'greek', + 'swedish', + 'czech', + 'arabic', + 'turkish', + 'polish', + 'german', + 'russian', + ], + ]; /** - * - * @param string $regExp - * @param array $options + * @param array $options + * @param RuleProviderInterface $provider */ - public function __construct($regExp = null, array $options = array()) + public function __construct(array $options = [], RuleProviderInterface $provider = null) { - $this->regExp = $regExp ? $regExp : self::LOWERCASE_NUMBERS_DASHES; - $this->options = array_merge($this->options, $options); + $this->options = array_merge($this->options, $options); + $this->provider = $provider ? $provider : new DefaultRuleProvider(); + + foreach ($this->options['rulesets'] as $ruleSet) { + $this->activateRuleSet($ruleSet); + } } /** @@ -801,7 +94,7 @@ public function slugify($string, $separator = '-') if ($this->options['lowercase']) { $string = mb_strtolower($string); } - $string = preg_replace($this->regExp, $separator, $string); + $string = preg_replace($this->options['regexp'], $separator, $string); return trim($string, $separator); } @@ -824,98 +117,38 @@ public function addRule($character, $replacement) /** * Adds multiple rules to Slugify. * - * @param array $rules + * @param array $rules * * @return Slugify */ public function addRules(array $rules) { foreach ($rules as $character => $replacement) { - $this->rules[$character] = $replacement; + $this->addRule($character, $replacement); } return $this; } /** - * Activates an additional ruleset. - * - * @param string $name Name of the ruleset. + * @param string $ruleSet * * @return Slugify - * - * @throws \InvalidArgumentException if the no ruleset with the given name exists */ - public function activateRuleset($name) + public function activateRuleSet($ruleSet) { - if (!isset($this->rulesets[$name])) { - throw new \InvalidArgumentException('Slugify does not contain a ruleset "'.$name.'".'); - } - - return $this->addRules($this->rulesets[$name]); - } - - /** - * Adds a ruleset to Slugify. - * - * @param string $name Name of the ruleset. - * @param array $rules Rules - * - * @return Slugify - */ - public function addRuleset($name, array $rules) - { - $this->rulesets[$name] = $rules; - - return $this; - } - - /** - * Returns the rulesets. - * - * @return array> Rulesets - */ - public function getRulesets() - { - return $this->rulesets; - } - - /** - * Sets the regular expression used to sanitize the slug - * - * @param string $regExp - * - * @return Slugify - */ - public function setRegExp($regExp) - { - $this->regExp = $regExp; - - return $this; - } - - /** - * @param array $options - * - * @return Slugify - */ - public function setOptions(array $options) - { - $this->options = array_merge($this->options, $options); - - return $this; + return $this->addRules($this->provider->getRules($ruleSet)); } /** * Static method to create new instance of {@see Slugify}. * - * @param string $regExp The regular expression to be applied to strings when calling slugify - * @param array $options + * @param array $options * * @return Slugify */ - public static function create($regExp = null, array $options = array()) + public static function create(array $options = []) { - return new static($regExp, $options); + return new static($options); } } diff --git a/src/SlugifyInterface.php b/src/SlugifyInterface.php index 0c0ca1b4..30361a94 100644 --- a/src/SlugifyInterface.php +++ b/src/SlugifyInterface.php @@ -29,6 +29,8 @@ interface SlugifyInterface * @param string $separator * * @return string + * + * @api */ public function slugify($string, $separator = '-'); } diff --git a/tests/Bridge/Silex/SlugifySilexProviderTest.php b/tests/Bridge/Silex/SlugifySilexProviderTest.php index 3f429968..5bf84444 100644 --- a/tests/Bridge/Silex/SlugifySilexProviderTest.php +++ b/tests/Bridge/Silex/SlugifySilexProviderTest.php @@ -40,7 +40,7 @@ public function register() $app->boot(); $this->assertArrayHasKey('slugify', $app); - $this->assertArrayHasKey('slugify.regex', $app); + $this->assertArrayHasKey('slugify.provider', $app); $this->assertArrayHasKey('slugify.options', $app); $this->assertInstanceOf('Cocur\Slugify\Slugify', $app['slugify']); } diff --git a/tests/Bridge/ZF2/SlugifyServiceTest.php b/tests/Bridge/ZF2/SlugifyServiceTest.php index 5ce2f94a..1f2f1c21 100644 --- a/tests/Bridge/ZF2/SlugifyServiceTest.php +++ b/tests/Bridge/ZF2/SlugifyServiceTest.php @@ -43,11 +43,11 @@ public function invokeWithoutCustomConfig() */ public function invokeWithCustomConfig() { - $sm = $this->createServiceManagerMock(array( - Module::CONFIG_KEY => array( - 'reg_exp' => '/([^a-z0-9.]|-)+/' - ) - )); + $sm = $this->createServiceManagerMock([ + Module::CONFIG_KEY => [ + 'options' => ['regexp' => '/([^a-z0-9.]|-)+/'] + ] + ]); $slugify = call_user_func($this->slugifyService, $sm); $this->assertInstanceOf('Cocur\Slugify\Slugify', $slugify); diff --git a/tests/RuleProvider/FileRuleProviderTest.php b/tests/RuleProvider/FileRuleProviderTest.php new file mode 100644 index 00000000..a9a74670 --- /dev/null +++ b/tests/RuleProvider/FileRuleProviderTest.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Cocur\Slugify\RuleProvider; + +use org\bovigo\vfs\vfsStream; +use PHPUnit_Framework_TestCase; + +/** + * FileRuleProviderTest + * + * @package Cocur\Slugify\RuleProvider + * @author Florian Eckerstorfer + * @copyright 2015 Florian Eckerstorfer + * @group unit + */ +class FileRuleProviderTest extends PHPUnit_Framework_TestCase +{ + /** + * @test + * @covers Cocur\Slugify\RuleProvider\FileRuleProvider::__construct() + * @covers Cocur\Slugify\RuleProvider\FileRuleProvider::getRules() + */ + public function getRulesReturnsRulesReadFromJsonFile() + { + vfsStream::setup('fixtures', null, [ + 'german.json' => '{"ä": "a"}', + 'austrian.json' => '{"ß": "sz"}', + ]); + + $provider = new FileRuleProvider(vfsStream::url('fixtures')); + + $this->assertEquals(['ä' => 'a'], $provider->getRules('german')); + $this->assertEquals(['ß' => 'sz'], $provider->getRules('austrian')); + } +} diff --git a/tests/SlugifyTest.php b/tests/SlugifyTest.php index 0a376538..0ea753d7 100644 --- a/tests/SlugifyTest.php +++ b/tests/SlugifyTest.php @@ -12,6 +12,7 @@ namespace Cocur\Slugify\Tests; use Cocur\Slugify\Slugify; +use Mockery; /** * SlugifyTest @@ -26,21 +27,34 @@ */ class SlugifyTest extends \PHPUnit_Framework_TestCase { + /** + * @var Slugify + */ private $slugify; + /** + * @var \Cocur\Slugify\RuleProvider\RuleProviderInterface|\Mockery\MockInterface + */ + private $provider; + public function setUp() { - $this->slugify = new Slugify(); + $this->provider = Mockery::mock('\Cocur\Slugify\RuleProvider\RuleProviderInterface'); + $this->provider->shouldReceive('getRules')->andReturn([]); + + $this->slugify = new Slugify([], $this->provider); } /** * @test - * @dataProvider provider + * @dataProvider defaultRuleProvider * @covers Cocur\Slugify\Slugify::slugify() */ - public function slugifyReturnsSlugifiedString($string, $result) + public function slugifyReturnsSlugifiedStringUsingDefaultProvider($string, $result) { - $this->assertEquals($result, $this->slugify->slugify($string)); + $slugify = new Slugify(); + + $this->assertEquals($result, $slugify->slugify($string)); } /** @@ -77,40 +91,16 @@ public function addRulesAddsMultipleRules() */ public function activateRulesetActivatesTheGivenRuleset() { - $this->assertInstanceOf( - 'Cocur\Slugify\Slugify', - $this->slugify->activateRuleset('esperanto') - ); - - $this->assertEquals( - 'sercxi-mangxi-hxirurgio-jxurnalo-sxuo-malgraux', - $this->slugify->slugify('serĉi manĝi ĥirurgio ĵurnalo ŝuo malgraŭ') - ); - } - - /** - * @test - * @covers Cocur\Slugify\Slugify::activateRuleset() - * @expectedException \InvalidArgumentException - */ - public function activateRulesetThrowsExceptionIfInvalidName() - { - $this->slugify->activateRuleset('invalid'); - } + $provider = Mockery::mock('\Cocur\Slugify\RuleProvider\RuleProviderInterface'); + $provider->shouldReceive('getRules')->with('esperanto')->once()->andReturn(['ĉ' => 'cx']); - /** - * @test - * @covers Cocur\Slugify\Slugify::addRuleset() - * @covers Cocur\Slugify\Slugify::getRulesets() - */ - public function addRulesetGetRulesets() - { + $slugify = new Slugify(['rulesets' => []], $provider); $this->assertInstanceOf( 'Cocur\Slugify\Slugify', - $this->slugify->addRuleset('foo', array('k' => 'key')) + $slugify->activateRuleset('esperanto') ); - $this->assertCount(2, $this->slugify->getRulesets()); + $this->assertEquals('sercxi', $slugify->slugify('serĉi')); } /** @@ -122,34 +112,15 @@ public function createReturnsAnInstance() $this->assertInstanceOf('Cocur\\Slugify\\SlugifyInterface', Slugify::create()); } - /** - * @test - * @covers Cocur\Slugify\Slugify::setRegExp() - */ - public function otherRegExpsProduceOtherResults() - { - $actual = 'File Name.tar.gz'; - $expected = 'file-name.tar.gz'; - - $this->assertNotEquals($expected, $this->slugify->slugify($actual)); - $this->assertInstanceOf( - 'Cocur\Slugify\Slugify', - $this->slugify->setRegExp('/([^a-z0-9.]|-)+/') - ); - $this->assertEquals($expected, $this->slugify->slugify($actual)); - } - /** * @test * @covers Cocur\Slugify\Slugify::__construct() */ public function constructWithOtherRegexp() { - $actual = 'File Name.tar.gz'; - $expected = 'file-name.tar.gz'; + $this->slugify = new Slugify(['regexp' => '/([^a-z0-9.]|-)+/']); - $this->slugify = new Slugify('/([^a-z0-9.]|-)+/'); - $this->assertEquals($expected, $this->slugify->slugify($actual)); + $this->assertEquals('file-name.tar.gz', $this->slugify->slugify('File Name.tar.gz')); } /** @@ -162,57 +133,42 @@ public function doNotConvertToLowercase() $actual = 'File Name'; $expected = 'File-Name'; - $this->slugify = new Slugify(null, array('lowercase' => false)); + $this->slugify = new Slugify(['lowercase' => false]); $this->assertEquals($expected, $this->slugify->slugify($actual)); } - /** - * @test - * @covers Cocur\Slugify\Slugify::setOptions() - */ - public function setOptionsSetsOptions() - { - $actual = 'File Name'; - $expected = 'File-Name'; - - $this->slugify = new Slugify(); - $this->slugify->setOptions(array('lowercase' => false)); - - $this->assertEquals($expected, $this->slugify->slugify($actual)); - } - - public function provider() + public function defaultRuleProvider() { - return array( - array(' a b ', 'a-b'), - array('Hello', 'hello'), - array('Hello World', 'hello-world'), - array('Привет мир', 'privet-mir'), - array('Привіт світ', 'privit-svit'), - array('Hello: World', 'hello-world'), - array('H+e#l1l--o/W§o r.l:d)', 'h-e-l1l-o-w-o-r-l-d'), - array(': World', 'world'), - array('Hello World!', 'hello-world'), - array('Ä ä Ö ö Ü ü ß', 'ae-ae-oe-oe-ue-ue-ss'), - array('Á À á à É È é è Ó Ò ó ò Ñ ñ Ú Ù ú ù', 'a-a-a-a-e-e-e-e-o-o-o-o-n-n-u-u-u-u'), - array(' â Ê ê Ô ô Û û', 'a-a-e-e-o-o-u-u'), - array(' â Ê ê Ô ô Û 1', 'a-a-e-e-o-o-u-1'), - array('°¹²³⁴⁵⁶⁷⁸⁹@₀₁₂₃₄₅₆₇₈₉', '0123456789at0123456789'), - array('Mórë thån wørds', 'more-thaan-woerds'), - array('Блоґ їжачка', 'blog-jizhachka'), - array('фильм', 'film'), - array('драма', 'drama'), - array('Ύπαρξη Αυτής η Σκουληκομυρμηγκότρυπα', 'iparxi-autis-i-skoulikomirmigkotripa'), - array('C’est du français !', 'c-est-du-francais'), - array('هذه هي اللغة العربية', 'hthh-hy-llgh-laarby'), - array('مرحبا العالم', 'mrhb-laa-lm'), - array('Één jaar', 'een-jaar'), - array('tiếng việt rất khó', 'tieng-viet-rat-kho'), - array('Nguyễn Đăng Khoa', 'nguyen-dang-khoa'), - array('နှစ်သစ်ကူးတွင် သတ္တဝါတွေ စိတ်ချမ်းသာ ကိုယ်ကျန်းမာ၍ ကောင်းခြင်း အနန္တနှင့် ပြည့်စုံကြပါစေ', 'nhitthitkutwin-thttwatwe-seikkhyaantha-koekyaanmaywae-kaungkhyin-anntnhin-pyisonkypase'), - array('Zażółć żółcią gęślą jaźń', 'zazolc-zolcia-gesla-jazn'), - array('Mężny bądź chroń pułk twój i sześć flag', 'mezny-badz-chron-pulk-twoj-i-szesc-flag'), - array('ერთი ორი სამი ოთხი ხუთი', 'erti-ori-sami-otkhi-khuti') - ); + return [ + [' a b ', 'a-b'], + ['Hello', 'hello'], + ['Hello World', 'hello-world'], + ['Привет мир', 'privet-mir'], + ['Привіт світ', 'privit-svit'], + ['Hello: World', 'hello-world'], + ['H+e#l1l--o/W§o r.l:d)', 'h-e-l1l-o-w-o-r-l-d'], + [': World', 'world'], + ['Hello World!', 'hello-world'], + ['Ä ä Ö ö Ü ü ß', 'ae-ae-oe-oe-ue-ue-ss'], + ['Á À á à É È é è Ó Ò ó ò Ñ ñ Ú Ù ú ù', 'a-a-a-a-e-e-e-e-o-o-o-o-n-n-u-u-u-u'], + [' â Ê ê Ô ô Û û', 'a-a-e-e-o-o-u-u'], + [' â Ê ê Ô ô Û 1', 'a-a-e-e-o-o-u-1'], + ['°¹²³⁴⁵⁶⁷⁸⁹@₀₁₂₃₄₅₆₇₈₉', '0123456789at0123456789'], + ['Mórë thån wørds', 'more-thaan-woerds'], + ['Блоґ їжачка', 'blog-jizhachka'], + ['фильм', 'film'], + ['драма', 'drama'], + ['Ύπαρξη Αυτής η Σκουληκομυρμηγκότρυπα', 'iparxi-autis-i-skoulikomirmigkotripa'], + ['C’est du français !', 'c-est-du-francais'], + ['هذه هي اللغة العربية', 'hthh-hy-llgh-laarby'], + ['مرحبا العالم', 'mrhb-laa-lm'], + ['Één jaar', 'een-jaar'], + ['tiếng việt rất khó', 'tieng-viet-rat-kho'], + ['Nguyễn Đăng Khoa', 'nguyen-dang-khoa'], + ['နှစ်သစ်ကူးတွင် သတ္တဝါတွေ စိတ်ချမ်းသာ ကိုယ်ကျန်းမာ၍ ကောင်းခြင်း အနန္တနှင့် ပြည့်စုံကြပါစေ', 'nhitthitkutwin-thttwatwe-seikkhyaantha-koekyaanmaywae-kaungkhyin-anntnhin-pyisonkypase'], + ['Zażółć żółcią gęślą jaźń', 'zazolc-zolcia-gesla-jazn'], + ['Mężny bądź chroń pułk twój i sześć flag', 'mezny-badz-chron-pulk-twoj-i-szesc-flag'], + ['ერთი ორი სამი ოთხი ხუთი', 'erti-ori-sami-otkhi-khuti'], + ]; } }