The previous article collected quite a few, sometimes quite drastic, comments, the second part will tell about the changes that occurred during the next 4 months and, if possible, will not repeat the first part, which is still very relevant.
For what
From the previous article, not everyone understood why all this is created, a specific problem that the product solves.
The easiest way to explain such things is by example. CleverStyle CMS will not work if:
- Under your task there is a CMS that solves the problem completely
- Under your task there is a CMS that almost fits, you will file it, updates don't particularly bother you.
- You have an Enterprise project
It will be suitable when you have a project for which there is no ready-made solution, and sawing something distant like will be a pile of crutches, which subsequently cannot be updated.
Singleton

')
Also in the comments many times the “antipattern” was mentioned as a loner, especially since the names of the system treit accompanied this.
In general, this is not exactly the loner that you could think of.
In fact, this is a slightly more complicated thing, providing:
- single point of creation of system objects and module objects
- customization of system classes, starting from the complete replacement, and ending with the support of patching one system class with several components at once ( more )
- caches the called classes so that even the patching of system objects does not significantly affect the performance
At first it seems that this is a terribly inflexible tool, but in fact it allows you to create various useful things, and you do not have to worry about it when using it.
In its simplest form:
$Session = \cs\Session::instance();
All that client code needs to know is that it will receive a session object with a predictable public interface, but this may not be the original system object, or even not at all.
It also allows you to generate hints in the IDE on all public methods and properties of system objects without any plug-ins and additional annotations, which is extremely convenient.
Analogy from Laravel:
$Session = $app->make('session')
That's just here for the IDE tips you need to write annotations.
And also the substituted Singleton for tests allows you to slip anything instead of the returned object, and this is
actively used .
Composer

There were a lot of comments about Composer, PSR4 and related. If you delve a little into the details of how components are installed and what their dependencies affect, it becomes clear that Composer, to put it mildly, is not the most suitable solution for packaging components.
“But it’s so convenient for installing libraries!” You will say, and you will undoubtedly be right.
It is not kosher to connect the same library several times as part of different components and to suffer because of different versions.
Therefore, in addition to the support of
composer.json ,
composer.lock and
vendor , a separate component with the unexpected name Composer has appeared at the root of the project!
During use, interaction with Composer itself, provided that the dependencies do not conflict is reduced to zero.
In order to take advantage of this delight, add a dependency on the
composer to the
meta.json component, and prescribe the dependencies themselves, an example for the WebSockets module:
{ "package" : "WebSockets", "category" : "modules", "version" : "0.29.0+build-45", "description" : "WebSockets server based on Ratchet and React with client-side bindings as well", "author" : "Nazar Mokrynskyi", "website" : "cleverstyle.org/cms", "license" : "MIT License", "db" : [ "pool" ], "db_support" : [ "MySQLi" ], "provide" : "websockets", "require" : [ "System>=2.1", "System<=3.0", "composer" ], "require_composer" : { "cboden/ratchet" : "0.3.*", "ratchet/pawl" : "0.1.*" }, "multilingual" : [ "interface" ], "hide_in_menu" : 1 }
During the component installation, Composer will assemble the dependencies of all components, make the final
composer.json , and if there are no conflicts, everything will be fixed by itself, if it does, the Composer console output will be reformatted into HTML and presented to the user, let him decide what to do about it.
This
composer.json generates a module for installing all dependencies:
{ "repositories" : [ { "type" : "package", "package" : { "name" : "modules\/Http_server", "version" : "0.8.0+build-13", "require" : {"react\/http" : "0.4.*"}, "dist" : { "url" : "\/web\/cscms.org\/www\/components\/modules\/Composer\/empty.zip", "type" : "zip" } } }, { "type" : "package", "package" : { "name" : "modules\/WebSockets", "version" : "0.24.0+build-38", "require" : { "cboden\/ratchet" : "0.3.*", "ratchet\/pawl" : "0.1.*" }, "dist" : { "url" : "\/web\/cscms.org\/www\/components\/modules\/Composer\/empty.zip", "type" : "zip" } } } ], "require" : { "modules\/Http_server" : "0.8.0+build-13", "modules\/WebSockets" : "0.24.0+build-38" } }
Virtual packages are declared on the spot, they are immediately dependent on them, so conflict resolution lies entirely on the standard Composer mechanisms (the zip file is the only thing you need to have in the file system, it is completely empty inside).
Separation of logic and representation

Ideally, no view on the server.
While ready as an example in the client part of the module store (below), although it will be updated using
JSON-LD for the minimum amount of server code and better indexing.
Now the product page of the store in the code looks like this:
<section data-date="0" data-id="1" data-in_stock="24" data-price="20" data-soon="0" is="cs-shop-item"> <div id="images"> <img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_031854a812c6b264b.jpg"> <img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_035654a812ec26d24.jpg"> <img alt="" src="http://cscms.org/storage/public/Plupload/2015-01-03/18/2_035654a812ec1c834.jpg"> </div> <div id="videos"> <a href="https://www.youtube.com/watch?v=rHBxJCq99jA"> </a> <a href="https://www.youtube.com/watch?v=bmtbg5b7_Aw"> </a> </div> <h1>Boots</h1> <div id="description"> <p>Nice boots</p> </div> <div id="attributes"> <table> <tr> <td>Size</td> <td>2</td> </tr> </table> </div> </section>
That is, it has nothing to do with how it looks on the page, how it is also
mentioned .
Coding style

I don’t really like what PSRs offer, so the coding style was slightly updated in the wiki, additionally now there are PhpStorm coding style and inspections configuration files in the repository, and when you open the project, it will immediately be configured properly.
All new files are formatted with this style, old files when editing too.
Please respect the style of the author of the project)
Refactoring

In the interval from version 1.0, the core was put in order, as a result of extensive refactoring, the system became significantly clearer and more predictable, as well as some functions became possible, such as working in Request / Response mode (more on that later).
Globally:
- the cs \ Trigger class was renamed to cs \ Event so as not to confuse it anymore, it was also simplified and new features appeared, like a one-time subscription to an event, like jQuery.fn.one ()
- additionally cs.Event appeared on the frontend with the same methods, the order of the arguments as cs \ Event on the server
- cs \ Session was formed after the next cs \ User refactoring, which makes it possible to further speed up the work in asynchronous mode
- cs \ Route combined routing functionality, which for historical reasons was simultaneously in cs \ Config and cs \ Index , which was far from obvious
- $ _SERVER wraps into an array-like object for easy retrieval of necessary information, regardless of configuration, this eliminates code duplication.
- \ ExitException is used instead of exit / die in those rare places where they were, third-party libraries are easily patched by automatic search and replace to support this functionality, a critical feature for Request / Response mode
- some of the built-in functions that work with the global context have been replaced with wrappers ( header () -> _header () ), third-party libraries are easily patched by automatic search and replace to support this functionality (or if namespaces are used, the user header is simply declared volume), critical feature for Request / Response mode
There is no sense to list many other changes,
release-notes.md has over 480 lines with a detailed description of the key changes and recommendations for a smooth update.
Partially refined system module, but only partially. More beautiful refactoring and more will be.
Static analysis

Previously, the entire static analysis consisted of
IDP PhpStorm inspections, but now each commit is additionally checked by
SensioLabsInsight and
Scrutinizer .
These two tools work wonders for static analysis. At the moment, all Major defects that they came across, and partly Minor / Warning, have been fixed.
Tools are actively used, their reports will decrease with each commit.
Releases

Starting from 1.110, all builds are automated, in the case of passing tests after each commit, the night build flies to SourceForge in the
nightly folder, if this is a release, the release version is assembled and falls into
stable / {version} in the same place.
This simplifies releases and removes all those inconveniences that arose with the publication of releases in the form of a page with links to files in Dropbox.
New features

First, some components that have been developed for a long time and are considered stable have grown to version 1.0.
Secondly, it would be insulting to state that out of the box no new functionality appeared in 4 months.
Http server
Once mentioned here . This is a module that implements the Http server in PHP, which allows processing multiple requests in a single process and has a very good effect on performance (several times).
If you follow a
few simple rules , all components will work in this mode without changes.
WebSockets
It was also there , it closely integrates WebSockets with CleverStyle CMS, allowing you to send data to the client and back almost in real time without undue burden, according to the principle of the device is similar to the server's Http module.
Score
A store module has appeared. An attempt has been made to create a general-purpose module, that is, there is no functionality for accumulative discounts out of the box, promotions, special offers, and all sorts of other things.
Nevertheless, the module has a set of events with the help of which all this can be quite simply implemented exactly in the form that you need.
Also, the entire client part is built on web components, and changes in absolutely every possible way, you are limited only by your imagination (there are no traditional templates and there will not be any).
Bitcoin payment
The store module supports plug-in payment systems using a very general purpose interface. This module is the first to implement this interface, providing the option to pay Bitcoin (there is automatic conversion of some currencies at the current rate).
Syntax highlighting
Somehow a blog needed syntax highlighting, the Prism library integration appeared for this purpose. The library, like everyone else, is patched to work with web components, is friends with visual editors.
At last

The system is actively developing, the code becomes cleaner, simpler, more understandable, it acquires new functionality, the documentation is constantly updated and maintained.
Backward compatibility preserved the entire branch of versions 1.x, version 1.110 was the last of this series.
The obsolete code was recently removed due to the upgrade to version 2.x, the minimum version requirement is now PHP 5.5+.
Provided that all upgrade recommendations have been implemented, upgrading from 1.110 to 2.x is rather trivial.
The easiest way to start and try
using DockerAll source code
on GitHub , ibid wiki with documentation.