themosis / framework

The Themosis framework core.
https://framework.themosis.com/
GNU General Public License v2.0
671 stars 121 forks source link

Split into front and backend components? #464

Closed lougreenwood closed 5 years ago

lougreenwood commented 6 years ago

Hello!

First, let me say thanks to everyone involved in build Themosis, it's an excellent foundation for building modern systems atop of WP.

Given the development of the WP REST API and possibility to now begin building apps which make use of JS or native mobile clients making use of a headless WP server component, has there been any consideration to split Themosis into front and backend packages?

Perhaps this isn't necessary and if a project doesn't make use of a Themosis theme, UI-related code isn't called?

Just wanted to put the suggestion out there and see what the community thinks. :)

jlambe commented 6 years ago

Thanks @lougreenwood.

Indeed, if you set to not use a WordPress theme (headless WordPress), WordPress will not handle the front-end. The API are still loaded, so if you focus your work on customizing the WordPress administration, you still get access to the View, Config, PostType, ... APIs.

What do you have in mind by splitting Themosis in front and backend packages?

lougreenwood commented 6 years ago

Hey @jlambe :)

I was thinking along the lines of moving the following components (but not limited to) into some new 'frontend' component:

Maybe not all of this would be appropriate as people may still want to be able to easily customise the WP admin UI, even if they're only using the simple 'backend' framework - but maybe that just requires the frontend framework.

But essentially, 'backend' (core?) would focus on building a Themosis/WP plugin, whereas 'frontend' would allow extending this to create a Themosis theme...

lougreenwood commented 6 years ago

I've been doing some digging around in the container for a separate task, but I noticed that pertinent to this conversation, the following providers all have instances registered with the container.

They seems like good examples of things which would likely not be necessary in a 'backend' project:

'twig.loader' => 
        object(Twig_Loader_Filesystem)[1715]
          protected 'paths' => 
            array (size=0)
              ...
          protected 'cache' => 
            array (size=0)
              ...
          protected 'errorCache' => 
            array (size=0)
              ...
          private 'rootPath' => string '/var/www/html/htdocs/' (length=21)
      'twig' => 
        object(Twig_Environment)[1714]
          protected 'charset' => string 'UTF-8' (length=5)
          protected 'loader' => 
            object(Twig_Loader_Filesystem)[1715]
              ...
          protected 'debug' => boolean true
          protected 'autoReload' => boolean true
          protected 'cache' => 
            object(Twig_Cache_Filesystem)[1716]
              ...
          protected 'lexer' => null
          protected 'parser' => null
          protected 'compiler' => null
          protected 'baseTemplateClass' => string 'Twig_Template' (length=13)
          protected 'extensions' => 
            array (size=5)
              ...
          protected 'parsers' => null
          protected 'visitors' => null
          protected 'filters' => null
          protected 'tests' => null
          protected 'functions' => null
          protected 'globals' => null
          protected 'runtimeInitialized' => boolean false
          protected 'extensionInitialized' => boolean false
          protected 'loadedTemplates' => null
          protected 'strictVariables' => boolean false
          protected 'unaryOperators' => null
          protected 'binaryOperators' => null
          protected 'templateClassPrefix' => string '__TwigTemplate_' (length=15)
          protected 'functionCallbacks' => 
            array (size=0)
              ...
          protected 'filterCallbacks' => 
            array (size=0)
              ...
          protected 'staging' => 
            object(Twig_Extension_Staging)[1720]
              ...
          private 'originalCache' => string '/twig' (length=5)
          private 'bcWriteCacheFile' => boolean false
          private 'bcGetCacheFilename' => boolean false
          private 'lastModifiedExtension' => int 0
          private 'extensionsByClass' => 
            array (size=5)
              ...
          private 'runtimeLoaders' => 
            array (size=0)
              ...
          private 'runtimes' => 
            array (size=0)
              ...
          private 'optionsHash' => string 'core:escaper:optimizer:debug:themosis:0:7:1:1.35.0:1:Twig_Template:0' (length=68)
          private 'loading' => 
            array (size=0)
              ...
      'loop' => 
        object(Themosis\View\Loop)[1726]
      'blade' => 
        object(Illuminate\View\Compilers\BladeCompiler)[1731]
          protected 'extensions' => 
            array (size=0)
              ...
          protected 'customDirectives' => 
            array (size=6)
              ...
          protected 'conditions' => 
            array (size=0)
              ...
          protected 'path' => null
          protected 'compilers' => 
            array (size=4)
              ...
          protected 'rawTags' => 
            array (size=2)
              ...
          protected 'contentTags' => 
            array (size=2)
              ...
          protected 'escapedTags' => 
            array (size=2)
              ...
          protected 'echoFormat' => string 'e(%s)' (length=5)
          protected 'footer' => 
            array (size=0)
              ...
          protected 'rawPlaceholder' => string '@__raw-block__@' (length=15)
          protected 'rawBlocks' => 
            array (size=0)
              ...
          protected 'files' => 
            object(Illuminate\Filesystem\Filesystem)[1730]
              ...
          protected 'cachePath' => string '/views/' (length=7)
          protected 'firstCaseInSwitch' => boolean true
          private 'encodingOptions' => int 15
          protected 'lastSection' => null
          protected 'forElseCounter' => int 0
      'view.engine.resolver' => 
        object(Illuminate\View\Engines\EngineResolver)[1728]
          protected 'resolvers' => 
            array (size=3)
              ...
          protected 'resolved' => 
            array (size=1)
              ...
      'view.finder' => 
        object(Themosis\View\ViewFinder)[1734]
          protected 'files' => 
            object(Illuminate\Filesystem\Filesystem)[1735]
              ...
          protected 'paths' => 
            array (size=6)
              ...
          protected 'views' => 
            array (size=0)
              ...
          protected 'hints' => 
            array (size=0)
              ...
          protected 'extensions' => 
            array (size=4)
              ...
      'view' => 
        object(Illuminate\View\Factory)[1727]
          protected 'engines' => 
            object(Illuminate\View\Engines\EngineResolver)[1728]
              ...
          protected 'finder' => 
            object(Themosis\View\ViewFinder)[1734]
              ...
          protected 'events' => 
            object(Illuminate\Events\Dispatcher)[1736]
              ...
          protected 'container' => 
            &object(Themosis\Foundation\Application)[1663]
          protected 'shared' => 
            array (size=2)
              ...
          protected 'extensions' => 
            array (size=5)
              ...
          protected 'composers' => 
            array (size=0)
              ...
          protected 'renderCount' => int 0
          protected 'componentStack' => 
            array (size=0)
              ...
          protected 'componentData' => 
            array (size=0)
              ...
          protected 'slots' => 
            array (size=0)
              ...
          protected 'slotStack' => 
            array (size=0)
              ...
          protected 'sections' => 
            array (size=0)
              ...
          protected 'sectionStack' => 
            array (size=0)
              ...
          protected 'loopsStack' => 
            array (size=0)
              ...
          protected 'pushes' => 
            array (size=0)
              ...
          protected 'prepends' => 
            array (size=0)
              ...
          protected 'pushStack' => 
            array (size=0)
              ...
          protected 'translationReplacements' => 
            array (size=0)
              ...
      'asset.finder' => 
        object(Themosis\Asset\AssetFinder)[1744]
          protected 'extensions' => 
            array (size=3)
              ...
          protected 'paths' => 
            array (size=1)
              ...
          protected 'files' => 
            array (size=2)
              ...
      'asset' => 
        object(Themosis\Asset\AssetFactory)[1751]
          protected 'finder' => 
            object(Themosis\Asset\AssetFinder)[1744]
              ...
          protected 'container' => 
            &object(Themosis\Foundation\Application)[1663]
          protected 'aliasPrefix' => string 'asset' (length=5)
          protected 'allowedAssets' => 
            array (size=4)
              ...
      'asset.themosis-core-styles' => 
        object(Themosis\Asset\Asset)[1752]
          protected 'area' => string 'admin' (length=5)
          protected 'allowedAreas' => 
            array (size=3)
              ...
          protected 'type' => string 'style' (length=5)
          protected 'args' => 
            array (size=5)
              ...
          protected 'key' => string 'themosis-core-styles' (length=20)
          protected 'action' => 
            object(Themosis\Hook\ActionBuilder)[1753]
              ...
          protected 'html' => 
            object(Themosis\Html\HtmlBuilder)[1755]
              ...
          protected 'filter' => 
            object(Themosis\Hook\FilterBuilder)[1754]
              ...
jlambe commented 6 years ago

@lougreenwood It all depends on what you're calling "backend" projects. If by "backend", you mean providing a custom administration site to manage data, if you're leveraging the WordPress admin for it, you might need those classes. If by "backend", you mean to only provide routes with REST endpoints, controllers and models, then I will say that there's no need for a Themosis stack.

lougreenwood commented 6 years ago

Yep, my use case is purely using WP REST endpoints and leveraging the organisation of Themosis to work make working with WP a bit less archaic :)

I disagree with your point that there's no need for a Themosis stack if the dev is just looking to make WP more like an MVC framework. I think you're under estimating the value of having something like Themosis available in the WP community and the effect it can have on leading developers away from a traditional 'WP' project. I believe it's also a great educational tool for budding WP devs...

If you're still open to discussing this, perhaps a better separation could be something like?

lougreenwood commented 6 years ago

I mean, take another look at the project description - it seems to me that it aligns perfectly well with a non-UI/MVC WP project (emphasis mine):

The Themosis framework is a tool aimed to WordPress developers of any levels. But the better WordPress and PHP knowledge you have the easier it is to work with.

Themosis framework is a tool to help you develop websites and web applications faster using WordPress. Using an elegant and simple code syntax, Themosis framework helps you structure and organize your code and allows you to better manage and scale your WordPress websites and applications.

😉

jlambe commented 6 years ago

@lougreenwood you're correct but I don't see the point to separate UI classes from logic classes. If it's a performance thing, i don't really think it's an issue. Classes are declared into the container but not loaded or instantiated until you ask for them. Plus I can see difficulties to maintain separate libraries. A plugin might need a way to generate quick UI to manage some data. I don't really see an added value here of splitting but perhaps I'm wrong but it would be great to have other people comment on this as well.