[RFC] Themes layout support
gildonei opened this issue · 35 comments
Summary
Theme support
Motivation
Reading the docs, I didn't found anything indicating that Ubiquity supports theme layouts, like CakePHP as a sample, Where I can have multiples themes and set the theme to be used on controller and It will render specified view with specific theme.
Compatibility with Ubiquity's philosophy
Indicate compatibility or improvements in:
- ease of use
- design modularity
Expected results
With theme support, we could develop projects and control design versions or create CMSs where users could choose his own theme to apply to his websites
Additional context
CakePHP theme support is a good refer to this feature
Hi,
I do not know how the cakePHP themes work.
Does a theme include a set of stylesheets, associated with predefined templates, giving the user the possibility to choose a presentation by selecting a theme,
or is it more complex?
Yes, CakePHP themes include a set of assets (css, js, others) and you can create all of your views according this theme.
In a specifc theme you can use Bootstrap 4, while in other theme you can use Semantic-ui, and in another you can use Foundation.
This website https://www.kenkopattofloripa.com.br and https://kenkopatto.lupahosting.com.br/ were developed with Cake using themes. Both domain use same database and CakePHP core, but domains were configured to load specific theme.
It's an interesting idea, to be productive more quickly with the framework.
The development of this module will consist of 2 phases:
-
Back-office : The development of the core part for the integration of themes in Ubiquity (you must first define a basic structure for the themes)
-
Front-office : The creation of themes usable by default (1 by major css framework )
The first part does not pose any particular problems.
On the other side, I'm not an expert for the second (I'm not a graphic designer).
Do you want to participate in development? or was it just a request for additional feature?
I could participate with documentation and testing those new functionalities. Maybe I could contribute with core code, but I don't know if my skills/knowledge about framework development will attend the needs.
In CakePHP 3, themes are build like Plugins having its own folders for assets and views and others stuff (https://book.cakephp.org/3.0/en/views/themes.html and https://book.cakephp.org/3.0/en/plugins.html#plugin-create-your-own).
I guess it could work similar or, it could be more like WordPress and in View layer could be a theme folder were themes could be placed with his skeleton and views, and the framework were shipped with a default-front and default-back theme inside themes folder for out of the box installation.
I could participate with documentation and testing those new functionalities. Maybe I could contribute with core code, but I don't know if my skills/knowledge about framework development will attend the needs.
This is not a problem
it's a good thing to start with testing, debugging, or writing documentation.
Any contribution is welcome!
It would be great if you could list the expected features (use cases) of this module, to build a product backlog.
I just watched the cakePHP 3 plugins ...
It's a bit like an application in the application, like the symfony bundles.
I wish more simplicity, the best thing that happened to symfony is to no longer require the use of Bundle since version 4.
The use of themes should solicit only the front part.
I agree with simplicity.
About expected features:
- Allows custom set of assest (each theme must have his own css, js, images,...)
- Possibility to load specific theme for a domain (domainA.com loads theme A, domainB.com loads theme B, and go on)
- Callback functions like beforeRender and afterRender for flow control
- Themes could support use of partial views (elements), that could be shared among them. (A sample is meta tags and oc tags that usually are the same on all themes, just like some phones, addresses, etc.
I guess that are some usefull features that could be implemented for themes
If I rephrase what you said:
- If the
themes moduleis loaded, at any time, there is anactiveTheme, which gives access to resources (assets) - This active theme can change conditionally (depending on the domain or other condition chosen by the developer/user)
- The theme does not modify the common parts (which are not in presentation)
- Some events are emitted before and after loading a theme, so that the user can act on the flow
I find that the most difficult choice to make is the provision of themes for the developer.
- If the themes are installable via Composer, it is a problem to customize them.
- If they are installed directly in the project, themes are easy to customize, but we can not update them anymore.
I think we have to mix these two solutions, but I do not know exactly how.
I'm going to look at how other frameworks work on this subject.
I guess that themes should be installed directly in the project by developers, as we are creating a framework, not a CMS like WordPress.
In a simple way, a theme will be a set of views (on MVC), that were created in a specific path according with previous variables set in a controller to render in a specific layout presentation.
Yes, you're right
Nevertheless, the updates are an eventuality.
I'm starting a prototype version on https://github.com/phpMv/ubiquity/tree/theme_module , just to lay the foundations.
You can contribute the way you want (commenting, coding, debugging, emitting new ideas...).
Deal! I will be following the updates and give help were I can
Hi gildonei,
if you want, you can test the addition of the Themes module by updating the devtools:
composer global require phpmv/ubiquity-devtools:dev-themes_module
You can then create a new project that includes the changes.
Ubiquity new test-themes -a
By default, 3 themes are integrated: Bootstrap, Foundation and Semantic-ui
Summary of the main specifications:
activeThemeis the active theme (configured in app/config/config.php)- The views of the themes are in
app/views/themes - Themes assets are in
public/assets - Scss files are provided and ready for compilation
- In twig,
@activeThemerefers to the location of the active theme
Some questions:
-
Where theme view files must be saved?
a) Inside theme folders like /app/view/themes/theme-name/View-folder-name/view-file.html?
b) Inside default view folders like /app/view/View-folder-name/view-file.html? -
How can I change theme in controller actions?
<?php
namespace controllers;
/**
* Controller Pessoas
**/
class Pessoas extends ControllerBase{
/**
* @activeTheme("name" => "bootstrap")
*/
public function index(){
$this->loadView('index.html');
}
/**
* @activeTheme("name" => "foundation")
*/
public function client_index(){
$this->loadView('index.html');
}
/**
* @activeTheme("name" => "custom")
*/
public function admin_index(){
$this->loadView('index.html');
}
}a) Inside theme folders like /app/view/themes/theme-name/View-folder-name/view-file.html?
Yes
and you can use @activeTheme for loading:
$this->loadView('@activeTheme/index.html');
For now, you can change the theme by:
ThemesManager::setActiveTheme('themeName');
@activeTheme annotation is a good idea (not yet implemented) !
Couldn't make it Work.
- config.php
<?php
#...
"templateEngineOptions"=>array(
"cache"=>"",
"activeTheme"=>"bootstrap"
),- Controller
<?php
#/app/controllers/Pessoas.php
namespace controllers;
use \Ubiquity\themes\ThemesManager;
/**
* Controller Pessoas
**/
class Pessoas extends ControllerBase{
/**
* Index view
*/
public function index(){
ThemesManager::setActiveTheme('custom');
$this->loadView('index.html'); // Didin't work
//$this->loadView('@activeTheme/index.html'); // Didin't work - got Fatal Error
//$this->loadView('custom/Pessoas/index.html'); // Didin't work - got Fatal Error
}
}Fatal error: Uncaught Twig\Error\LoaderError: Unable to find template "custom/Pessoas/index.html" (looked into: C:\wamp64\www\ubiquity\themes\.ubiquity\..\app\\views). in C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php:239 Stack trace: #0 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php(148): Twig\Loader\FilesystemLoader->findTemplate('custom/Pessoas/...') #1 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(300): Twig\Loader\FilesystemLoader->getCacheKey('custom/Pessoas/...') #2 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(382): Twig\Environment->getTemplateClass('custom/Pessoas/...') #3 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(360): Twig\Environment->loadTemplate('custom/Pessoas/...') #4 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(319): Twig\Environment->load('custom/Pessoas/...') #5 C:\wamp64\www\ubiquity\themes\vendor\phpmv\ubiquity\src\Ubiquity\views\engine\Twig.php(98): in C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php on line 239
- Views
- /app/views/themes/custom/main.html (copied from bootstrap and changed title and body content)
<!DOCTYPE html>
<html>
<head>
{% block header %}
<base href="{{config["siteUrl"]}}">
<meta charset="UTF-8">
<title>CUSTOM THEME</title>
{% endblock %}
{% block css %}
{{css_('css/style.css')}}
{{css_('css/all.min.css')}}
<!-- {{css('https://cdnjs.cloudflare.com/ajax/libs/mdbootstrap/4.7.4/css/mdb.min.css')}} -->
{% endblock %}
</head>
<body>
{% block head %}
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<span class="navbar-brand mb-0 h1">Custom theme test</span>
</div>
</nav>
{% endblock %}
{% block body %}
{% endblock %}
{% block footer %}
{% endblock %}
{% block scripts %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
{% endblock %}
</body>
</html>- /app/views/themes/custom/Pessoas/index.php
<h1>Hello World!</h1>Expected Result
A page with hello world content using custom theme or simply hello world
Result obtained
Same bootstrap default page
An improvement
Using web-tools, view creations should use default theme folder or ask for a theme to save new files to save files in correct path
you should use:
$this->loadView('@activeTheme/index.html');
On the homepage, does the top menu allow you to switch from one framework to another?
@activeTheme
I tried this, and got a Fatal Error.
Fatal error: Uncaught Twig\Error\LoaderError: Unable to find template "@activeTheme/index.html" (looked into: C:\wamp64\www\ubiquity\themes\.ubiquity\..\app\\views\themes\bootstrap). in C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php:239 Stack trace: #0 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php(148): Twig\Loader\FilesystemLoader->findTemplate('@activeTheme/in...') #1 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(300): Twig\Loader\FilesystemLoader->getCacheKey('@activeTheme/in...') #2 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(382): Twig\Environment->getTemplateClass('@activeTheme/in...') #3 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(360): Twig\Environment->loadTemplate('@activeTheme/in...') #4 C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Environment.php(319): Twig\Environment->load('@activeTheme/in...') #5 C:\wamp64\www\ubiquity\themes\vendor\phpmv\ubiquity\src\Ubiquity\views\engin in C:\wamp64\www\ubiquity\themes\vendor\twig\twig\src\Loader\FilesystemLoader.php on line 239
Yes, on the home page, it allows to change the theme, also got a notice on top of page is not a valid value for database cache
this notice is because in config.php database.cache => "" instead of false, and every time I have to reload cache, it turns to empty value deleting false when I update
yes, it's normal, I did not really expect the change of Framework at runtime.
I do not even know if it's a feature to implement.
For now, you can perform the theme change as in the ct() method of IndexController.
It worked, using code below.
<?php
namespace controllers;
use \Ubiquity\themes\ThemesManager;
/**
* Controller Pessoas
**/
class Pessoas extends ControllerBase{
/**
* Index view
*/
public function index(){
ThemesManager::setActiveTheme('custom');
$this->loadView('@activeTheme/Pessoas/index.html');
}
}I guess that should not be necessary to inform view folder name /Pessoas/ to load view. I think it could be more "magic" like when you not use a theme
and where is the Pessoas folder located?
Inside /themes/theme-name-folder/
/app/themes/custom/Pessoas/
so it's normal that you have to put @activeTheme/Pessoas/index.html
It may be the loadDefaultView method that could automatically load a template located in /themes/{activeTheme}/{controllerName}/{actionName}.html for the action controllerName::actionName
How can I use the loadDefaultView method ?
Currently loadDefaultView() loads the file views/{controllerName}/{actionName}.html
By doing :
$this-> loadDefaultView ();
in {controllerName}::{actionName}
I have not adapted this method yet for themes...
but it's this method that could be more "magic"
When you have time, will you be able to test the new version of devtools?
For creating a new project with bootstrap and semantic
Ubiquity new testProject -a -t=bootstrap,semantic
For adding foundation in a project:
Ubiquity install-theme foundation
For adding a non existing theme in a project -> error
Ubiquity install-theme xxTheme
For creating a new theme in a project
Ubiquity create-theme myTheme
For creating a new theme inheriting from bootstrap in a project
Ubiquity create-theme myBootstrap -x=bootstrap
For creating a new theme inheriting from bootstrap5 in a project -> error
Ubiquity create-theme myBootstrap5 -x=bootstrap5
For creating a new controller associated with a view when there is an active theme
Ubiquity controller TestBootstrapController -v
For creating a new action associated with a view in a controller when there is an active theme
Ubiquity action TestBootstrapController.testAction -v
Scheduled for tomorrow!
For creating a new project with bootstrap and semantic
Ubiquity new testProject -a -t=bootstrap,semantic
+/-, it installed Ubiquity without errors, but home page came with all 3 themes, including foundation
For adding foundation in a project:
Ubiquity install-theme foundation
This theme seems to be already installed in C:\wamp64\www\ubiquity\themeProject/public/assets/foundation!
For adding a non existing theme in a project -> error
Ubiquity install-theme xxTheme
OK - The theme xxTheme does not exists! Would-you like to create a new one (y/n) ? Works great
For creating a new theme in a project
Ubiquity create-theme myTheme
Works fine! All folders were succefully created
For creating a new theme inheriting from bootstrap in a project
Ubiquity create-theme myBootstrap -x=bootstrap
Works fine! All folders were succefully created and files copied
For creating a new theme inheriting from bootstrap5 in a project -> error
Ubiquity create-theme myBootstrap5 -x=bootstrap5
OK, got expected error! (The theme bootstrap5 does not exists!)
For creating a new controller associated with a view when there is an active theme
Ubiquity controller TestBootstrapController -v
OK - controller were created at last active theme in use
For creating a new action associated with a view in a controller when there is an active theme
Ubiquity action TestBootstrapController.testAction -v
View files were created outside theme folder, i think it should be created inside active theme folder or inside specified theme param in devtools. Also I think the created action should have the ThemesManager::setTheme code inserted before render;
Thank you very much for your work!
I will look at the few problems reported
I fixed the errors, and implemented the theme management in the webtools.
If you wish, you can test by putting the devtools on the dev-master branch (the merge has been done).
composer global require phpmv/ubiquity-devtools:dev-masterA project is created by default without activated theme, I think it's easier like that.
The user adds themes if he wants (with devtools or with webtools)
OK! Later I will try to implement AdminLTE - https://adminlte.io/- as a backend theme and tell you about the results.
Great, it's a good idea, the addition of themes is indeed extensible.