├── .github └── workflows │ └── test-application.yaml ├── .gitignore ├── CHANGELOG.md ├── README.md ├── composer.json ├── phpunit.xml.dist ├── src ├── CallbackSlugifier.php └── SlugifierInterface.php └── tests └── CallbackSlugifierTest.php /.github/workflows/test-application.yaml: -------------------------------------------------------------------------------- 1 | name: Test application 2 | 3 | on: 4 | pull_request: 5 | push: 6 | branches: 7 | - 'master' 8 | 9 | jobs: 10 | test: 11 | name: 'PHP ${{ matrix.php-version }}' 12 | runs-on: ubuntu-20.04 13 | 14 | strategy: 15 | fail-fast: false 16 | matrix: 17 | include: 18 | - php-version: '5.6' 19 | - php-version: '7.1' 20 | - php-version: '7.4' 21 | - php-version: '8.0' 22 | 23 | steps: 24 | - name: Checkout project 25 | uses: actions/checkout@v2 26 | 27 | - name: Install and configure PHP 28 | uses: shivammathur/setup-php@v2 29 | with: 30 | php-version: ${{ matrix.php-version }} 31 | tools: 'composer:v2' 32 | 33 | - name: Install dependencies with Composer 34 | uses: ramsey/composer-install@v1 35 | with: 36 | dependency-versions: ${{ matrix.dependencies }} 37 | composer-options: --prefer-dist 38 | 39 | - name: Execute test cases 40 | run: vendor/bin/simple-phpunit 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | phpunit.xml 2 | composer.lock 3 | vendor 4 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | ========= 3 | 4 | 2.1.0 5 | ----- 6 | 7 | * Allow installation with PHP 8. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Symfony CMF Slugifier API 2 | 3 | [![Build Status](https://travis-ci.org/symfony-cmf/slugifier-api.svg?branch=master)](https://travis-ci.org/symfony-cmf/slugifier-api) 4 | [![Latest Stable Version](https://poser.pugx.org/symfony-cmf/slugifier-api/version.png)](https://packagist.org/packages/symfony-cmf/slugifier-api) 5 | [![Total Downloads](https://poser.pugx.org/symfony-cmf/slugifier-api/d/total.png)](https://packagist.org/packages/symfony-cmf/slugifier-api) 6 | 7 | This package is part of the [Symfony Content Management Framework (CMF)](http://cmf.symfony.com/) 8 | and licensed under the [MIT License](LICENSE). 9 | 10 | A "slugifier" is a function which transforms a string `such as this` into a 11 | URL-friendly string `such-as-this`. Slugifiers are also known as "urlizers". 12 | 13 | This package does not contain a slugifier implementation, it provides a 14 | standard interface (`SlugifierInterface`) for use by third party slugifiers 15 | and a `CallbackSlugifier` that is capable of wrapping most non-implementing 16 | third-party slugifiers to the `SlugifierInterface`. 17 | 18 | ## Requirements 19 | 20 | * See also the `require` section of [composer.json](composer.json) 21 | 22 | ## Documentation 23 | 24 | Perhaps the best way to document this simple component is with a 25 | demonstration. You have an event subscriber which slugifies the title of a 26 | blog post: 27 | 28 | ```php 29 | slugifier = $slugifier; 40 | } 41 | 42 | public function onEntitySave(\Some\Event $event) 43 | { 44 | $entity = $event->getEntity(); 45 | $entity->setSlug($this->slugifier->slugify($entity->getTitle()); 46 | } 47 | } 48 | ``` 49 | 50 | You can then inject either a slugifier which already implements the CMF 51 | ``SlugifierInterface`` or you can use non-implementing libraries using the 52 | `CallbackSlugifier`. Using non-implementing libraries is very easy, assume 53 | you want to use the [`aferrandini/urlizer`](https://github.com/aferrandini/Urlizer) 54 | package (which is also used by the [RoutingAutoBundle](https://github.com/symfony-cmf/RoutingAutoBundle)), 55 | you can configure the `CallbackSlugifier` object to call the `Ferrandini\Urlizer::urlize()` 56 | method: 57 | 58 | ```php 59 | $slugifier = new CallbackSlugifier('Ferrandini\Urlizer::urlize'); 60 | $fooSubscriber = new FooSubscriber($slugifier); 61 | ``` 62 | 63 | By using the Slugifier package you decouple your application from the slugifier 64 | implementation. 65 | 66 | See also: 67 | 68 | * [All Symfony CMF documentation](http://symfony.com/doc/master/cmf/index.html) - complete Symfony CMF reference 69 | * [Symfony CMF Website](http://cmf.symfony.com/) - introduction, live demo, support and community links 70 | 71 | ## FIG Proposal 72 | 73 | We [proposed this to FIG](https://groups.google.com/forum/?fromgroups=#!topic/php-fig/J-6s9Wlyk-A) 74 | but unfortunately the proposal did not get enough interest. We would still be 75 | happy to contribute this to a PSR should the interest come up and deprecate 76 | this package in favor of the PSR one. 77 | 78 | ## Contributing 79 | 80 | Pull requests are welcome. Please see our 81 | [CONTRIBUTING](https://github.com/symfony-cmf/symfony-cmf/blob/master/CONTRIBUTING.md) 82 | guide. 83 | 84 | Unit and/or functional tests exist for this bundle. See the 85 | [Testing documentation](http://symfony.com/doc/master/cmf/components/testing.html) 86 | for a guide to running the tests. 87 | 88 | Thanks to 89 | [everyone who has contributed](https://github.com/symfony-cmf/RoutingBundle/contributors) already. 90 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "symfony-cmf/slugifier-api", 3 | "description": "Provides a basic slugifier interface to transform text into strings suitable for URLs", 4 | "keywords": ["slugify", "urlize"], 5 | "homepage": "http://cmf.symfony.com", 6 | "license": "MIT", 7 | "authors": [ 8 | { 9 | "name": "Symfony CMF Community", 10 | "homepage": "https://github.com/symfony-cmf/slugifier-api/contributors" 11 | } 12 | ], 13 | "require": { 14 | "php": "^5.6|^7.0|^8.0" 15 | }, 16 | "require-dev": { 17 | "symfony/phpunit-bridge": "^5.2" 18 | }, 19 | "autoload": { 20 | "psr-4": { "Symfony\\Cmf\\Api\\Slugifier\\": "src/" } 21 | }, 22 | "autoload-dev": { 23 | "psr-4": { "Symfony\\Cmf\\Api\\Slugifier\\Tests\\": "tests/" } 24 | }, 25 | "extra": { 26 | "branch-alias": { 27 | "dev-master": "2.0-dev" 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | ./tests/ 12 | 13 | 14 | 15 | 16 | 17 | . 18 | 19 | Tests/ 20 | vendor/ 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/CallbackSlugifier.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | class CallbackSlugifier implements SlugifierInterface 20 | { 21 | protected $callback; 22 | 23 | /** 24 | * @param callable $callback 25 | */ 26 | public function __construct($callback) 27 | { 28 | if (!is_callable($callback)) { 29 | throw new \InvalidArgumentException(sprintf('Expected a valid callable as callback, %s given.', gettype($callback))); 30 | } 31 | 32 | $this->callback = $callback; 33 | } 34 | 35 | /** 36 | * {@inheritdoc} 37 | */ 38 | public function slugify($string) 39 | { 40 | return call_user_func($this->callback, $string); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/SlugifierInterface.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | interface SlugifierInterface 20 | { 21 | /** 22 | * Return a slugified (or urlized) representation of a given string. 23 | * 24 | * @param string $string 25 | * 26 | * @return string 27 | */ 28 | public function slugify($string); 29 | } 30 | -------------------------------------------------------------------------------- /tests/CallbackSlugifierTest.php: -------------------------------------------------------------------------------- 1 | createCallbackSlugifier(); 22 | $this->assertEquals('this-is-slugified', $slugifier->slugify('this is slugified')); 23 | } 24 | 25 | public static function slugify($val) 26 | { 27 | return str_replace(' ', '-', $val); 28 | } 29 | 30 | /** 31 | * @return CallbackSlugifier 32 | */ 33 | private function createCallbackSlugifier() 34 | { 35 | return new CallbackSlugifier(__CLASS__.'::slugify'); 36 | } 37 | } 38 | --------------------------------------------------------------------------------