GithubHelp home page GithubHelp logo

raffaelj / cpmultiplane Goto Github PK

View Code? Open in Web Editor NEW
16.0 4.0 3.0 1.68 MB

small PHP frontend for Cockpit CMS

License: MIT License

PHP 46.88% JavaScript 14.68% Hack 4.16% SCSS 13.67% Dockerfile 0.39% CSS 20.22%

cpmultiplane's Introduction

CpMultiplane

A small PHP front end for the fast and headless Cockpit CMS.

Docs (work in progress), i18n


CpMultiplane is not compatible with Cockpit CMS v2.

See also Cockpit CMS v1 docs, Cockpit CMS v1 repo and Cockpit CMS v2 docs, Cockpit CMS v2 repo.


My main goals:

  1. privacy by design and privacy by default
  2. developer friendliness
  • no plugins to deactivate half of the core features needed
  • ability to adjust everything
  1. clean and structured backend for my clients - Cockpit CMS with addons and modifications
  2. structured data - keep the system and the data portable and future proof
  3. modular, small and reusable code
  4. semantic html, responsive css, usable without javascript
  5. multilingualism by design

CpMultiplane is no classic Cockpit addon. It uses Cockpit as a library, registers multiplane as a new module and than uses cockpit's core features. The backend still works as a standalone tool to manage and structure data.

It is the refactored version of Monoplane, which is not maintained anymore.

Requirements

  • PHP >= 7.1
  • PDO + SQLite (or MongoDB)
  • GD extension
  • pecl intl extension (optional)
  • mod_rewrite, mod_versions enabled (on apache)

Make also sure that $_SERVER['DOCUMENT_ROOT'] exists and is set correctly.

You can find the detailed version and a cli install example in docs/installation.

Installation

manually

  • copy all files of this repository into your web root
  • copy .htaccess.dist to .htaccess
  • copy Cockpit in a subfolder of your web root and name it cockpit
  • copy additional addons, create your collections, adjust some settings

via git

cd ~/html
git clone https://github.com/raffaelj/CpMultiplane.git .
cp .htaccess.dist .htaccess
git clone https://github.com/agentejo/cockpit.git cockpit
git clone https://github.com/raffaelj/cockpit_CpMultiplaneGUI.git cockpit/addons/CpMultiplaneGUI
git clone https://github.com/raffaelj/cockpit_FormValidation.git cockpit/addons/FormValidation
git clone https://github.com/raffaelj/cockpit_UniqueSlugs.git cockpit/addons/UniqueSlugs

via composer

cd ~/html
composer create-project --ignore-platform-reqs raffaelj/cpmultiplane .

If you use composer, Cockpit and the addons CpMultiplaneGUI, FormValidation and UniqueSlugs are installed automatically.

via docker

The docker image comes preinstalled with the quickstart routine of the "basic" template, with a default admin user (password: admin) and with dummy data from installed addons.

This is not meant for production use, but for local development.

docker pull raffaelj/cpmultiplane
docker run --rm -d --name cpmultiplane -p 8080:80 raffaelj/cpmultiplane

Now open your browser on localhost:8080 and see it in action.

Features

  • pages and sub pages (e. g. posts)
  • multilingual with language prefix, e. g.: example.com/en/my-page
  • 2 modes for structured content
    1. one collection per content type, e. g. a collection named pages and a collection named posts
    2. a single collection named pages - each entry has a type page or post (experimental)
  • maintenance mode with option for allowed ips
  • simple content preview while editing pages
  • two basic responsive themes with scss files
  • simple privacy notice banner, that gets enabled when clicking on video link
  • contact forms - fully functional without javascript
  • pre-rendering of markdown fields
  • multiple ways to change everything
  • GUI via CpMultiplaneGUI addon
  • full-text search
  • ...

Recommended Addons

Install these addons in cockpit/addons/.

  • CpMultiplaneGUI
    • adds a few fields to the sidebar, so you don't have to define them in your collection definitions
    • some gui tweaks for easier access
    • work in progress...
  • UniqueSlugs
    • If links should point to slug instead of _id
    • for multilingual slugs in language switch
  • rljUtils
    • fixes security issues in Admin UI for multi user setups
    • big language buttons for multilingual setups
  • FormValidation
    • The inbuilt Forms Controller requires field definitions from this addon
    • The inbuilt views and css files are written to match the field definitions
  • VideoLinkField
    • inbuilt /assets/js/mp.js, some views and css files are designed to load videos privacy friendly with a privacy notice, that pops up only when a user clicks a play button
  • SimpleImageFixBlackBackgrounds
    • replaces the SimpleImage library with a modified version to fix black backgrounds of transparent png and gif files on hosts with a non-bundled PHP GD version
  • EditorFormats - if you want to give your users a Wysiwyg field

Intended use

Backend - Cockpit

  1. Create a singleton site for your default page definitions.
  2. Create a collection pages for all of your pages.
  3. Create a collection posts for all of your blog posts.
  4. Use the CpMultiplaneGUI addon.

Frontend - CpMultiplane

  1. create a child theme of rljbase or create your own theme
  2. adjust defaults in /child-theme/config/config.php
  3. add snippets to /child-theme/bootstrap.php, that are explicitly for your theme
  4. add snippets to /config/bootstrap.php, that are specifically for your setup
  5. change some partials to fit your needs

Settings

The fastest way to change some defaults, is to add some values to /cockpit/config/config.php:

<?php
return [
    'app.name' => 'CpMultiplane',

    'i18n' => 'en',
    'languages' => [
        'default' => 'English',
        'de' => 'Deutsch',
    ],

    // define settings here
    'multiplane' => [
        'pages' => 'pages',
        'siteSingleton' => 'site',
        'slugName' => 'slug',
        'use' => [
            'collections' => [
                'pages',
                'posts',
                'products',
            ],
            'singletons' => [
                'site',
            ],
            'forms' => [
                'contact',
            ],
        ],
    ],
];

The cleaner and more user friendly way is to use the GUI. Create a profile, name it my-profile and set multiplane to the profile name:

return [
    'app.name' => 'CpMultiplane',

    'i18n' => 'en',
    'languages' => [
        'default' => 'English',
        'de' => 'Deutsch',
    ],

    // define settings via profile
    'multiplane' => [
        'profile' => 'my-profile',
    ],
];

Reserved routes

  • /login - Calling example.com/login reroutes to the admin folder, e. g. example.com/cockpit
  • /search - full-text search
  • /getImage - Calling /getImage?src=assets_id?w=100&h=100&m=thumbnail returns images/thumbnails with predefined settings, that can be adjusted with params
  • /submit/form_name and /form/form_name - for contact forms
  • /getPreview and /livePreview for content preview
  • /clearcache to clear cockpit's cache (only in debug mode)

Copyright and License

Copyright 2019 Raffael Jesche under the MIT license.

See LICENSE for more information.

Credits and third party resources

Without Cockpit, CpMultiplane couldn't exist. Thanks to Artur Heinze and to all contributors.

cpmultiplane's People

Contributors

raffaelj avatar raruto avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

cpmultiplane's Issues

to do before 0.3.0 release

There are a lot of changes, I rewrote multiple code parts and I did a lot of cleanup. In all of my tests, everything seems to work with different data models (but I tested only with a very small data set):

  • type based and collection based sub pages
  • _id, slug and permalink as identifiers
  • monolingual and multilingual

To do

  • [ ] write snippet or addon to create unique permalinks --> could be implemented in UniqueSlugs addon

CpMultiplaneGUI

  • add new options
    • usePermalinks (experimental)
    • structure
    • fieldNames instead of slugName
  • auto update pages collection, use and structure, if one of them changes
  • remove posts collection option --> it should have no effect anymore

Docs

  • [ ] migration guide from 0.2.4 to 0.3.0
    • [ ] backwards incompatibilities with $posts
    • [ ] I had to change @base() to @route() in some partials (e.g. pagination) for permalink usage. This effects (child) theme templates in multilingual setups.

Other

I planned to do a forms cleanup and to implement seo friendly image urls in 0.3.0.

  • forms cleanup OR delay it to 0.4.0 --> delayed
  • seo friendly image urls OR delay it to 0.4.0 --> implemented

pagination for sub pages doesn't work if page type detection is "type"

It works, if the sub pages are on the home page without a slug, but not if they are on a different page with a slug.

Example:
10 pages, 2 of type page and 8 of type post, both pages have the same posts

  • startpage
  • blog

Working:
example.com/ - displays first 5 entries below text
example.com/page/2 - displays entry 6 to 8 below text

Not working:
example.com/blog/ - displays first 5 entries below text
example.com/blog/page/2 - 404

If the start page doesn't have posts, example.com/page/2 displays the start page without posts.

restructure layouts and partials in views/themes

The current situation is messy. The root of a theme folder should look like this:

.
├── assets
│   ├── css
│   └── js
├── config
│       config.php
├── base
│       index.php
│       search.php
│       ...
├── layouts
│       base.php
│       ...
├── partials
│       breadcrumbs.php
│       ...
│   bootstrap.php
│   package.json
│   README.md
│   screenshot.png

add themes sass to npm build

Just because I have ruby sass, I don't have to use it anymore. npm run build should build not only js, but also css.

mobile nav should contain all navigations

The current implementation displays only the main nav when clicking on the nav bar icon on small screens. It should contain the footer nav (all navigations), too.

Routes file

Hi raffaelj,
I know you are already thinking of rewriting the whole project.

By chance, is it worth renaming the following file bind.php to something less generic? (eg. routes.php)

Have a nice Holidays,
Raruto

add support for permalinks (instead/additional to slugs)

started to implement permalink support...

You have to set slugName to the permalink field.

Problems

In multilingual setups, the base_url contains the language prefix, so $app->baseUrl('/addons') returns /de/addons. $app->routeUrl() still returns / --> expected behaviour.

I used @base() in multiple templates, which translates to $app->baseUrl().

Internal (search, sub pages, nav, language switch...) some urls are created "manually" by applying base_url + /lang + /parent_page + /slug. This needs some cleanup.

But the recent updates in the permalink update branch seem to work :-)

tested/working setups:

  • single language, 2 collections (pages, posts), posts are sub pages,
    • theme: rljbase
    • theme: rljstripes
    • theme: mpdocs
  • multilingual, 2 collections (pages, posts), posts are sub pages,
    • theme: rljbase
    • theme: rljstripes
    • theme: mpdocs
  • single language, 1 collection (pages), pages of type "post" are sub pages,
    • theme: rljbase
    • theme: rljstripes
    • theme: mpdocs
  • multilingual, 1 collection (pages), pages of type "post" are sub pages,
    • theme: rljbase
    • theme: rljstripes
    • theme: mpdocs

Gotchas:

  • permalink must start with /
  • permalink must not end with /
  • if multilingual, permalinks must contain the language prefix /de/addons
  • permalinks in subpages must contain the permalink of parent page, e. g. /addons/uniqueslugs

duplicated urls with/without trailing slash

bad for SEO - I thought, I fixed that already, but maybe it was in a different project.

Possible solutions

  • reroute via .htaccess
  • reroute via $app->bind('/*', function(){})
  • keep both versions and a canonical url to the html head

Blocked by

Should the trailing slash be the default?

Con: Urls without the slash look cleaner.
Pro: If a trailing slash is the default, the urls match the pattern of SSGs, so moving is easier.

I tend to use trailing slashes as default, but I have to think about it.

add category and tags pages

Pages and posts can have tags already and they are displayed with badges. They should be links to overview pages, that filter by tags.

bind routes:

  • /tag/:tag_name --> all page types
  • /category/:category_name
  • /blog/tag/:tag_name --> all posts with tag_name

Advanced tags search/selection should be possible, e. g. filter by tag_name1 and tag_name2, but omit posts with tag_name3...

Installation docs

Hi,

please provide a documentation how to setup cockpit for CpMultiplane (Fields for singletons, collections, etc..).

update logo

Multiplanes have more wings than monoplanes - low priority

add hard coded structure for sub pages and multilingual sites

What?
Set the structure of pages and posts or other sub pages via config file. This configuration is optional.

Why?
Parent page routes are always the same, but they cause database requests if called multiple times from different locations.

I'm actually not sure, if I really need it, but I keep that issue open as a reminder.

restructure forms

The structure grew over time with multiple changes in the Multiplane files and in the FormValidation addon. At first, I didn't think about the possibility to have multiple forms on the same page. I only had types of forms in mind (contact form, newsletter subscription, comment section)...

to do

  • move html helper functions to a helper class
  • add js to use the form with ajax requests and client side validation (it still must work without js!)
  • all form parts should be in one location (or in less, clearly arranged locations), maybe as own module/addon
    • partials in rljbase theme
      • /widgets/contactform.php
      • /partials/form.php
      • /partials/formfields/*.php
    • /module/forms.php
    • /Controller/Forms.php
  • move some php from partials to controller/helper
  • improve multilingual forms
    • all form labels and info texts are translated via config i18n file
    • form field contents should be translatable, too
    • translations should be in FormValidation addon instead of i18n file, so it doesn't break when users change the forms
  • document, how to use the FormValidation addon with CpMultiplane

PHPDoc blocks

Hi Raffael,

whenever possible prefer PHP docblocks over inline comments, for example, at the following line:

// modified version of Lime\fetch_from_array()
'get' => function($index, $default = null) {
if (\is_null($index)) {
return null;
} elseif (isset($this->$index)) {
return $this->$index;
} elseif (\strpos($index, '/')) {
$keys = \explode('/', $index);
switch (\count($keys)){
case 1:
if (isset($this->{$keys[0]})){
return $this->{$keys[0]};
}
break;
case 2:
if (isset($this->{$keys[0]}[$keys[1]])){
return $this->{$keys[0]}[$keys[1]];
}
break;
case 3:
if (isset($this->{$keys[0]}[$keys[1]][$keys[2]])){
return $this->{$keys[0]}[$keys[1]][$keys[2]];
}
break;
case 4:
if (isset($this->{$keys[0]}[$keys[1]][$keys[2]][$keys[3]])){
return $this->{$keys[0]}[$keys[1]][$keys[2]][$keys[3]];
}
break;
}
}
return \is_callable($default) ? \call_user_func($default) : $default;
}, // end of get()

I use this atom plugin to make writing easier, you can try to check if this kate plugin it still working.

Happy holidays,
Raruto

ignore html tags in full-text search (wysiwyg)

Searching for queries like "href" or "header" etc. should be ignored when searching.

Possible solutions:

  • change regex to ignore content between <...>
  • create hidden field with stripped tags when saving field
  • create helper collection with stripped content, that updates dynamically

cli `update-htaccess` creates new line at end of file

Running ./mp multiplane/update-htaccess creates new lines at the end of .htaccess after running it multiple times, which happens automatically when using composer update.

Solution 1: remove empty line at EOF in .htaccess.dist
Solution 2 (cleaner): Don't use the whole dist file as replacement string, but only the text inside '/# BEGIN CpMultiplane.*# END CpMultiplane/s'

seo friendly image urls

change lexy img src to ImageResize profiles (if present) or/and implement something better, than the getImage route

ideas:

image profiles

  • create mutitple image sizes when saving an asset (via ImageResize addon or via ImageStyles addon) and store them in profile name folders
  • add a route to /image/profile_name/asset_id/seo-friendly-title-slug.jpg
  • store the image on the fly in a directory, that matches the profile, so if it exists already, no php interpreter is needed

unique slugs for assets

  • similar to unique slugs for collection entries, but for assets
  • route: /image/seo-fiendly-asset-slug.jpg
  • should also have predifined profiles

possible route detection

  • /image/:profile/:asset_id
  • /image/:profile/:asset_slug
  • /image/:width/:height/:quality/:asset_id.:format
  • ...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.