{"id":15045062,"url":"https://github.com/orbitale/cmsbundle","last_synced_at":"2025-05-06T21:29:44.910Z","repository":{"id":26243010,"uuid":"29689970","full_name":"Orbitale/CmsBundle","owner":"Orbitale","description":"Super-lightweight CMS bundle for Symfony","archived":false,"fork":false,"pushed_at":"2021-12-15T13:59:41.000Z","size":382,"stargazers_count":61,"open_issues_count":5,"forks_count":14,"subscribers_count":6,"default_branch":"4.x","last_synced_at":"2025-05-01T01:57:43.270Z","etag":null,"topics":["cms","cms-bundle","hacktoberfest","php","symfony","symfony-bundle"],"latest_commit_sha":null,"homepage":"https://demo.orbitale.io/orbitale_cms/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Orbitale.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":"pierstoval"}},"created_at":"2015-01-22T17:11:00.000Z","updated_at":"2025-04-18T15:04:18.000Z","dependencies_parsed_at":"2022-09-18T14:13:54.397Z","dependency_job_id":null,"html_url":"https://github.com/Orbitale/CmsBundle","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orbitale%2FCmsBundle","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orbitale%2FCmsBundle/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orbitale%2FCmsBundle/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Orbitale%2FCmsBundle/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Orbitale","download_url":"https://codeload.github.com/Orbitale/CmsBundle/tar.gz/refs/heads/4.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252771737,"owners_count":21801771,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cms","cms-bundle","hacktoberfest","php","symfony","symfony-bundle"],"created_at":"2024-09-24T20:51:24.506Z","updated_at":"2025-05-06T21:29:44.877Z","avatar_url":"https://github.com/Orbitale.png","language":"PHP","funding_links":["https://github.com/sponsors/pierstoval"],"categories":[],"sub_categories":[],"readme":"\n[![SensioLabsInsight](https://insight.sensiolabs.com/projects/dcb6d7ad-83c6-458d-acd6-8dde8b8020bc/mini.png)](https://insight.sensiolabs.com/projects/dcb6d7ad-83c6-458d-acd6-8dde8b8020bc)\n[![Coverage Status](https://coveralls.io/repos/Orbitale/CmsBundle/badge.svg?branch=master)](https://coveralls.io/r/Orbitale/CmsBundle?branch=master)\n[![Build Status](https://travis-ci.org/Orbitale/CmsBundle.svg?branch=master)](https://travis-ci.org/Orbitale/CmsBundle)\n[![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Orbitale/CmsBundle/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Orbitale/CmsBundle/?branch=master)\n\n:warning: You're looking at the 4.x branch documentation.\u003cbr\u003e\nIf you need information about 3.x, go [here](https://github.com/Orbitale/CmsBundle/tree/3.x)\nIf you need information about 2.x, go [here](https://github.com/Orbitale/CmsBundle/tree/2.x)\nIf you need information about 1.x, go [here](https://github.com/Orbitale/CmsBundle/tree/1.x)\n\n##### Index\n\n* [Requirements](#requirements)\n* [Install](#install)\n* [Setup](#setup)\n* [Usage](#usage)\n * [Manage pages](#manage-pages)\n * [View pages](#view-pages)\n * [Generate a route based on a single page](#generate-a-route-based-on-a-single-page)\n* [Change homepage](#change-homepage)\n* [Page restriction based `host` and/or `locale`](#page-restriction)\n* [Design](#design)\n * [Using different layouts](#using-different-layouts)\n * [Advanced layout configuration](#advanced-layout-configuration)\n * [Changing the \"breadcrumbs\" look](#breadcrumbs)\n* [Setup EasyAdminBundle to manage pages and categories in its back-end](#easyadmin)\n* [Configuration reference](#configuration-reference)\n* [Changelog](#changelog)\n\n# Orbitale CMS Bundle\n\nThis bundle is a simple helper to create a very simple CMS based on a classic system with Pages and Categories.\n\n## Requirements\n\n* PHP 7.0+\n* Symfony 3.0+\n* Doctrine ORM\n\n## Install\n\nRequire the bundle by using [Composer](https://getcomposer.org/):\n\n```shell\n$ composer require orbitale/cms-bundle\n```\n\n## Setup\n\nRegister the necessary bundles in your Kernel:\n\n```php\n\u003c?php\n// app/AppKernel.php\npublic function registerBundles()\n{\n    $bundles = [\n        // ...\n        new Orbitale\\Bundle\\CmsBundle\\OrbitaleCmsBundle(),\n    ];\n}\n\n```\n\n### Import the necessary routing files.\n\n*Warning:*\n Both `Page` and `Category` controllers have to be \"alone\" in their routing path,\n because there is a \"tree\" routing management. If you set the prefix as \"/\"\n or any other path you are already using, make sure that `OrbitaleCmsBundle`\n routes are loaded **at the end of your routing file**, or you may have some\n unexpected \"404\" or other errors, depending on the routes priority.\u003cbr\u003e\n This is why we recommend you to **load the `CategoryController` _before_ the\n `PageController`**, and let both routes config be **the last ones** of your\n `routing.yml` file.\u003cbr\u003e\n **Note:** In technical terms, the whole URI is scanned, not a simple part of it,\n this is why it can analyze very deep URIs like\n `/home/blog/parent-link/child-link/element`, and check all pages/categories.\n\nExample:\n\n```yml\n# app/config/routing.yml\norbitale_cms_category:\n    resource: \"@OrbitaleCmsBundle/Resources/config/routing/categories.yaml\"\n    prefix:   /category/\n\norbitale_cms_page:\n    resource: \"@OrbitaleCmsBundle/Resources/config/routing/pages.yaml\"\n    prefix:   /page/\n```\n\n### Create your entities\n\nThis bundle supports Doctrine ORM only.\n\nIn order to use it, you must create your own entities and configure the bundle with them.\n\nUpdate your config:\n\n```yml\n# app/config/config.yml\norbitale_cms:\n    page_class: AppBundle\\Entity\\Page\n    category_class: AppBundle\\Entity\\Category\n```\n\n#### Create the `Page` entity and add it to your config\n\n```php\n\u003c?php\n\nnamespace AppBundle\\Entity;\n\nuse Orbitale\\Bundle\\CmsBundle\\Entity\\Page as BasePage;\nuse Doctrine\\ORM\\Mapping as ORM;\n\n/**\n * @ORM\\Entity(repositoryClass=\"Orbitale\\Bundle\\CmsBundle\\Repository\\PageRepository\")\n * @ORM\\Table(name=\"orbitale_cms_pages\")\n */\nclass Page extends BasePage\n{\n    /**\n     * @var int\n     * @ORM\\Column(name=\"id\", type=\"integer\")\n     * @ORM\\Id\n     * @ORM\\GeneratedValue(strategy=\"AUTO\")\n     */\n    protected $id;\n\n    /**\n     * @return int\n     */\n    public function getId()\n    {\n        return $this-\u003eid;\n    }\n}\n```\n\n#### Create the `Category` entity and add it to your config\n\n```php\n\u003c?php\n\nnamespace AppBundle\\Entity;\n\nuse Orbitale\\Bundle\\CmsBundle\\Entity\\Category as BaseCategory;\nuse Doctrine\\ORM\\Mapping as ORM;\n\n/**\n * @ORM\\Entity(repositoryClass=\"Orbitale\\Bundle\\CmsBundle\\Repository\\CategoryRepository\")\n * @ORM\\Table(name=\"orbitale_cms_categories\")\n */\nclass Category extends BaseCategory\n{\n    /**\n     * @var int\n     * @ORM\\Column(name=\"id\", type=\"integer\")\n     * @ORM\\Id\n     * @ORM\\GeneratedValue(strategy=\"AUTO\")\n     */\n    protected $id;\n\n    /**\n     * @return int\n     */\n    public function getId()\n    {\n        return $this-\u003eid;\n    }\n}\n\n```\n\n### Update your db schema\n\nUpdate your database by executing this command from your Symfony root directory:\n\n```bash\n$ php app/console doctrine:schema:update --force\n```\n\n## Usage\n\n### Manage pages\n\nTo manage your pages, you should use any back-end solution, like\n[EasyAdmin](https://github.com/javiereguiluz/EasyAdminBundle/) (which we suggest)\nor [SonataAdmin](https://sonata-project.org/bundles/admin), or any other backend\nsolution that can operate CRUD actions on entities.\nYou must have configured it to manage at least the\n`Orbitale\\Bundle\\CmsBundle\\Entity\\Page` entity.\n\n### View pages\n\nThe `PageController` handles some methods to view pages with a single\n`indexAction()`, and the `CategoryController` uses its route to show all pages\nwithin a specified `Category`.\n\nThe URI for both is simply `/{slug}` where `slug` is the... page or category slug.\n\nIf your page or category has one `parent`, then the URI is the following:\n`/{parentSlug}/{slug}`.\n\nYou can notice that we respect the pages hierarchy in the generated url.\n\nYou can navigate through a complex list of pages or categories, as long as they\nare related as `parent` and `child`.\n\nThis allows you to have such urls like this one :\n`http://www.mysite.com/about/company/team/members` for instance, will show only\nthe `members` page, but its parent has a parent, that has a parent, and so on,\nuntil you reach the \"root\" parent. And it's the same behavior for categories.\n\n*Note:* this behavior is the precise reason why you have to use a specific rules\nfor your routing, unless you may have many \"404\" errors.\n\n### Generate a route based on a single page\n\n*Note:* This behavior also works for categories.\n\nIf you have a `Page` object in a view or in a controller, you can get the whole\narborescence by using the `getTree()` method, which will navigate through all\nparents and return a string based on a separator argument (default `/`, for urls).\n\nLet's get an example with this kind of tree:\n\n```\n/ - Home (root url)\n├─ /welcome       - Welcome page (set as \"homepage\", so \"Home\" will be the same)\n│  ├─ /welcome/our-company            - Our company\n│  ├─ /welcome/our-company/financial  - Financial\n│  └─ /welcome/our-company/team       - Team\n└─ Contact\n```\n\nImagine we want to generate the url for the \"Team\" page. You have this `Page`\nobject in your view/controller.\n\n```twig\n    {# Page : \"Team\" #}\n    {{ path('orbitale_cms_page', {\"slugs\": page.tree}) }}\n    {# Will show : /welcome/our-company/team #}\n```\n\nOr in a controller:\n\n```php\n    // Page : \"Team\"\n    $url = $this-\u003egenerateUrl('orbitale_cms_page', ['slugs' =\u003e $page-\u003egetTree()]);\n    // $url === /welcome/our-company/team\n```\n\nWith this, you have a functional tree system for your CMS!\n\n## Change homepage\n\nThe homepage is always the first `Page` object with its `homepage` attribute set\nto true. Be sure to have only one element defined as homepage, or you may have\nunexpected results.\n\nYou can have multiple homepages if you add them restrictions based on host and\nlocale (see [next chapter](#page-restriction)).\n\n## \u003ca name=\"page-restriction\"\u003e\u003c/a\u003ePage restriction based `host` and/or `locale`\n\nIf you are hosting your application in a multi-domain platform, you can use the\n`host` attribute in your page to restrict the view only to the specified host.\n\nIt's great for example if you want to have different articles on different\ndomains like `blog.mydomain.com` and `www.mydomain.com`.\n\nIf you want to restrict by `locale`, you can specify the locale in the page.\nThe best conjointed use is with prefixed routes in the routing file:\n\n```yml\n# app/config/routing.yml\norbitale_cms_page:\n    resource: \"@OrbitaleCmsBundle/Controller/PageController.php\"\n    type:     annotation\n    # Add the locale to the prefix for if the page's locale is specified and is\n    # not equal to request locale, the app will return a 404 error.\n    prefix:   /{_locale}/page/\n```\n\n## Design\n\n`OrbitaleCmsBundle` has some options to customize the design of your simple CMS.\n\nMostly, you will take care of the `layouts` option (see\n[next chapter](#using-different-layouts)), or the `design` option.\n\n### Using different layouts\n\nObviously, the default layout has no style.\n\nTo change the layout, simply change the OrbitaleCmsBundle configuration to add\nyour own layout:\n\n```yaml\n# app/config/config.yml\norbitale_cms:\n    layouts:\n        front: { resource: @App/layout.html.twig } # The Twig path to your layout\n```\n\nWithout overriding anything, you can easily change the layout for your CMS!\n\nTake a look at the [default layout](Resources/views/default_layout.html.twig)\nto see which Twig blocks are mandatory to render correctly the pages.\n\n### Advanced layout configuration\n\nThe basic configuration for a layout is to specify a template to extend.\n\nBut if you look at the [Configuration reference](#configuration-reference) you\n will see that there are many other parameters you can use to define a layout:\n\nPrototype of a layout configuration:\n* **name** (attribute used as key for the layouts list):\u003cbr\u003e\n The name of your layout. Simply for readability issues, and maybe to get it\n directly from the config (if you need it).\n* **resource**:\u003cbr\u003e\n The Twig template used to render all the pages (see the [above](#using-different-layouts) section)\n* **assets_css** and *assets_js*:\u003cbr\u003e\n Any asset to send to the Twig `asset()` function. The CSS is rendered in the\n `stylesheets` block, and js in the `javascripts` block.\n* **host**:\u003cbr\u003e\n The exact domain name you want the layout to match with.\n* **pattern**:\u003cbr\u003e\n The regexp of the path you want to match with for this layout.\n It's nice if you want to use a different layout for categories and pages. For\n example, you can specify a layout for the `^/page/` pattern, and another for\n `^/category/`.\n If you specify a very deep pattern, you can even change the layout for a single\n page!\n\nTake another look on the [config reference](#configuration-reference) if you\nneed to get the prototype defaults.\n\n:warning: **Warning!** The **first matching** layout will be used, as well as\n routing would do, so be sure to configure them in the right order!\u003cbr\u003e\nEmpty values won't be taken in account.\n\n### \u003ca name=\"breadcrumbs\"\u003e\u003c/a\u003eChanging the \"breadcrumbs\" look\n\nUnder the `design` option, you have some that you can use to optimize the\nrendering of the breadcrumbs.\n\nBasically, it will look like this:\n\n[Homepage](#breadcrumbs) \u003e [Parent page](#breadcrumbs) \u003e Current page\n\n**Note:** The breadcrumbs wrapper already has `id=\"breadcrumbs\"` on its tag.\n\n* **breadcrumbs_class**:\u003cbr\u003e\n  Changes the class of the breadcrumbs wrapper.\n* **breadcrumbs_link_class**:\u003cbr\u003e\n  Changes the class of any link in the breadcrumbs.\n* **breadcrumbs_current_class**:\u003cbr\u003e\n  Changes the class of the current page in the breadcrumbs (which is not a link).\n* **breadcrumbs_separator** *(default: \"\u003e\")*:\u003cbr\u003e\n  Changes the default separator used. You can use anything, but mostly we see `\u003e`,\n  `/`, `|` or `*` on the web.\u003cbr\u003e\n  **Note:** This character is escaped in twig, so do not use things like `\u0026larr;`\n  or the `\u0026` sign will be replaced with `\u0026amp;` (as well as other characters).\n* **breadcrumbs_separator_class**:\u003cbr\u003e\n  You can specify a class for the separator (which is wrapped by a `\u003cspan\u003e` tag),\n  if you want to use special design or interaction on it.\n\n## Cache\n\nIf you want to cache your cms results, just activate it via the config:\n\n```yml\n    cache:\n        enabled: true\n        ttl: 300\n```\n\nIt uses Doctrine Result Cache so you need to activate it:\n\n```yml\n    doctrine:\n        orm:\n            result_cache_driver: apcu\n```\n\nYou can read more about DoctrineCache \u003ca href=\"http://symfony.com/doc/current/reference/configuration/doctrine.html#caching-drivers\"\u003ehere\u003c/a\u003e.\n\n## \u003ca name=\"easyadmin\"\u003e\u003c/a\u003eSetup EasyAdminBundle to manage pages and categories in its back-end\n\nThis configuration allows you to manage your pages and categories directly in the [EasyAdminBundle](https://github.com/javiereguiluz/EasyAdminBundle) way.\n\nFirst, install `EasyAdminBundle`, and set it up by reading its documentation (view link above).\n\nAfter you installed it, you can add this configuration to inject your new classes in EasyAdmin:\n\n```yml\n# app/config/config.yml\neasy_admin:\n    entities:\n        Pages:\n            label: admin.cms.pages\n            class: App\\Entity\\Page\n            show:\n                fields: [ id, parent, title, slug, tree, content, metaDescription, metaTitle, category, host, locale, homepage, enabled ]\n            list:\n                fields: [ id, parent, title, slug, tree, host, locale, { property: homepage, type: boolean }, { property: enabled, type: boolean } ]\n            form:\n                fields: [ title, slug, content, metaDescription, metaTitle, metaKeywords, css, js, category, parent, host, homepage, enabled ]\n\n        Categories:\n            label: \"Cms Categories\"\n            class: App\\Entity\\Category\n            show:\n                fields: [ id, parent, title, slug, tree, content, host, locale, homepage, enabled ]\n            list:\n                fields: [ id, parent, name, slug, description, { property: enabled, type: boolean } ]\n            form:\n                fields: [ name, slug, description, parent, enabled ]\n```\n\n## Configuration reference\n\n```yml\n# app/config/config.yml\norbitale_cms:\n    page_class: ~              # Required, must extend Orbitale Page class\n    category_class: ~          # Required, must extend Orbitale Category class\n    layouts:\n        # Prototype\n        name:\n            name:       ~      # Optional, it's automatically set from the key if it's a string\n            resource:   ~      # Required, must be a valid twig template\n            assets_css: []     # Injected with the `asset()` twig function\n            assets_js:  []     # Injected with the `asset()` twig function\n            pattern:    ~      # Regexp\n            host:       ~      # Exact value\n    design:\n        breadcrumbs_class:           \"breadcrumb\"  # The default value automatically suits to Bootstrap\n        breadcrumbs_link_class:      \"\"\n        breadcrumbs_current_class:   \"\"\n        breadcrumbs_separator:       \"\u003e\"\n        breadcrumbs_separator_class: \"breadcrumb-separator\"\n    cache:\n        enabled: false\n        ttl: 300\n\n```\n\n## Changelog\n\nGo to the [releases](https://github.com/Orbitale/CmsBundle/releases) page to see what are the changes between each\nnew version of Orbitale CmsBundle!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forbitale%2Fcmsbundle","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Forbitale%2Fcmsbundle","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Forbitale%2Fcmsbundle/lists"}