PHPackages                             workofstan/mycms - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. workofstan/mycms

ActiveLibrary

workofstan/mycms
================

MyCMS - Brief MVC framework for interactive websites including general administration.

v0.5.2(1w ago)14.6k↓100%proprietaryPHPPHP &gt;=7.2 &lt;8.6CI passing

Since Oct 6Pushed 1w agoCompare

[ Source](https://github.com/WorkOfStan/mycms)[ Packagist](https://packagist.org/packages/workofstan/mycms)[ RSS](/packages/workofstan-mycms/feed)WikiDiscussions main Synced today

READMEChangelog (10)Dependencies (10)Versions (40)Used By (0)

MyCMS
=====

[](#mycms)

[![Total Downloads](https://camo.githubusercontent.com/4057d9b0ca15fd344e358c9aa65fa44af7e366817d9184b9701ca93671ad32bf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f776f726b6f667374616e2f6d79636d732e737667)](https://packagist.org/packages/workofstan/mycms)[![Latest Stable Version](https://camo.githubusercontent.com/cdca027a55716eece3ab90d622e61690f111481c102e870b31dd8bdaef7e71f3/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f776f726b6f667374616e2f6d79636d732e737667)](https://packagist.org/packages/workofstan/mycms)[![Lint Code Base](https://github.com/WorkOfStan/mycms/actions/workflows/linter.yml/badge.svg)](https://github.com/WorkOfStan/mycms/actions/workflows/linter.yml)[![PHP Composer + PHPUnit + PHPStan](https://github.com/WorkOfStan/mycms/actions/workflows/php-composer-phpunit.yml/badge.svg)](https://github.com/WorkOfStan/mycms/actions/workflows/php-composer-phpunit.yml)

Brief MVC framework for interactive sites including general administration. This framework allows you to create an app just by simple configuration and keeping the framework up-to-date by composer while letting you use the vanilla PHP as much as possible. It works as a devstack which you install and then write your classes specific for your project. The boilerplate project is prepared in `dist` folder to be adapted as needed and it uses this `WorkOfStan\MyCMS` library out-of-the-box.

MyCMS is designed to be used with following technologies:

- [jQuery](https://jquery.org/) and [Bootstrap (version 4)](https://getbootstrap.com/docs/4.0/components/): for presentation
- [Latte](http://latte.nette.org/): for templating
- [MySQL](https://dev.mysql.com/)/[MariaDB](http://mariadb.com): for database backend
- [Tracy](https://github.com/nette/tracy): for debugging
- [Nette\\SmartObject](https://doc.nette.org/en/3.0/smartobject): for ensuring strict PHP rules
- [Psr\\Log\\LoggerInterface](https://www.php-fig.org/psr/psr-3/): for logging
- [WorkOfStan\\Backyard\\BackyardMysqli](https://github.com/WorkOfStan/backyard/blob/main/classes/BackyardMysqli.php): for wrapping SQL layer

Installation
------------

[](#installation)

Apache modules `mod_alias` (for hiding non-public files) and `mod_rewrite` (for friendly URL features) are expected.

Once [composer](https://getcomposer.org/) is installed, execute the following command in your project root to install this library:

```
composer require workofstan/mycms:^0.5.1
```

Most of library's classes use prefix `My`. To develop your project, create your own classes as children inheriting MyCMS' classes in the `./classes/` directory and name them without the initial `My` in its name.

```
$MyCMS = new \WorkOfStan\MyCMS\MyCMS(
    [
        // compulsory
        'logger' => $logger, // object \Psr\Log\LoggerInterface
        //optional
    ]
);

//Finish with Latte initialization & Mark-up output
$MyCMS->renderLatte(DIR_TEMPLATE_CACHE, "\\vendor\\ProjectName\\Latte\\CustomFilters::common", $params);
```

Files `process.php` and `admin-process.php` MUST exist as they process forms.

Note: `$MyCMS` name is expected by `ProjectSpecific extends ProjectCommon` class (@todo replace global $MyCMS by parameter handling)

Note/todo: MyCMS requires godsdev/tools which is stack with PHP/7. Therefore MyCMS is limited by PHP/7 as well.

Deployment
----------

[](#deployment)

### `/dist`

[](#dist)

Folder `/dist` contains initial *distribution* files for a new project using MyCMS, therefore copy it to your new project folder in order to start easily. Replace the string `MYCMSPROJECTNAMESPACE` with your project namespace. (TODO: rector...) Replace the string `MYCMSPROJECTSPECIFIC` with other site specific information (Brand, Twitter address, phone number, database table\_prefix in phinx.yml...). If you want to use your own table name prefix, please change the database related strings before first running [`./build.sh`](dist/build.sh).

To adapt the content and its structure either adapt migrations [content\_table](dist/db/migrations/20200607204634_content_table.php) and [content\_example](dist/db/migrations/20200703213436_content_example.php)before first running build or adapt the database content after running build or run build, see for yourself how it works, then adapt migrations, drop tables and run build again.

The table with users and hashed passwords is named `TAB_PREFIX . 'admin'`.

It is recommanded to adapt classes Contoller.php, FriendlyUrl.php and ProjectSpecific.php to your needs following the recommendations in comments. For deployment look also to [Deployment chapter](dist/README.md#deployment) and [Language management](dist/README.md#language-management) in dist/README.md.

MyCMS is used only as a library, so the project using it SHOULD implement `RedirectMatch 404 vendor\/` statement as prepared in `dist/.htaccess` to keep the library hidden from web access.

Admin UI
--------

[](#admin-ui)

Admin UI is displayed by MyAdmin::outputAdmin in this structure:

NavigationSearchAgendasMainElement overview:

Navigation = SpecialMenuLinks + Media+User+SettingsSearchAgendas (as in $AGENDAS in admin.php)Messages
Workspace: table/row/media/user/project-specific
Dashboard: List of tables### Navigation

[](#navigation)

- special Admin::outputSpecialMenuLinks
- default: Media+User+Settings MyAdmin::outputNavigation

### Search

[](#search)

- Admin class variable `$searchColumns` defines an array in format database\_table =&gt; \[`id`, list of fields to be searched in\], e.g.

```
    protected $searchColumns = [
        'product' => ['id', 'name_#', 'content_#'], // "#" will be replaced by current language
    ];
```

### Agendas

[](#agendas)

- MyAdmin::outputAgendas
- defined in $AGENDAS in admin.php

### Main

[](#main)

- Messages
- Workspace: one of the following
    - `$_GET['search']` =&gt; MyAdmin::outputSearchResults
    - `$_GET['table']` =&gt; MyAdmin::outputTable -- `$_GET['where']` is array =&gt; Admin::outputTableBeforeEdit . MyAdmin::tableAdmin-&gt;outputForm . Admin::outputTableAfterEdit -- `$_POST['edit-selected']` =&gt; MyAdmin::outputTableEditSelected(false) -- `$_POST['clone-selected']` =&gt; MyAdmin::outputTableEditSelected(true) -- else =&gt; Admin::outputTableBeforeListing . MyAdmin::tableAdmin-&gt;view . Admin::outputTableAfterListing
    - `$_GET['media']` =&gt; MyAdmin::outputMedia media upload etc.
    - `$_GET['user']` =&gt; MyAdmin::outputUser user operations (logout, change password, create user, delete user)
    - Admin::projectSpecificSectionsCondition =&gt; Admin::projectSpecificSection project-specific admin sections
- Dashboard: List of tables MyAdmin::outputDashboard

Admin notes
-----------

[](#admin-notes)

### Database

[](#database)

Columns of tables displayed in admin can use various features set in the comment:

commentfeature`{"display":"html"}`HTML editor Summernote{"display":"layout-row"}??{"display":"option"}Existing values are offered in select box{"display":"option","display-own":1}... and an input box for adding previously unused values{"display":"path"}??{"display":"texyla"}?? Texyla editor{"edit": "input"}zatím nic: todo: natáhnout string z prvního pole na stránce a webalize{"edit":"json"}rozpadne interní JSON do příslušných polí --- ovšem pokud prázdné, je potřeba vložit JSON (proto je default '{}'){"foreign-table":"category","foreign-column":"category\_en"}odkaz do jiné tabulky ke snadnému výběru{"foreign-table":"category","foreign-column":"category\_en","foreign-path":"path"}??{"required":true}??TODO: active=0/1 display as on/off button

TODO: better explain.

### clientSideResources

[](#clientsideresources)

In `class/Admin.php` you can redefine the `clientSideResources` variable with resources to load to the admin. Its default is:

```
    protected $clientSideResources = [
        'js' => [
            'scripts/jquery.js',
            'scripts/popper.js',
            'scripts/bootstrap.js',
            'scripts/admin.js?v=' . PAGE_RESOURCE_VERSION,
        ],
        'css-pre-admin' => [
            'styles/bootstrap.css',
        ],
        'css' => [
            'styles/font-awesome.css',
            'styles/ie10-viewport-bug-workaround.css',
            'styles/bootstrap-datetimepicker.css',
            'styles/summernote.css',
            'styles/admin.css?v=' . PAGE_RESOURCE_VERSION,
        ]
    ];
```

`admin.css` may be inherited to a child project, however as vendor folder SHOULD have denied access from browser, the content of that standard `admin.css` MUST be available through method `MyAdmin::getAdminCss`.

Testing
-------

[](#testing)

Run from a command line:

```
./vendor/bin/phpunit
```

Note that `dist` folder contains the starting MyCMS based project deployment and testing runs through `dist` as well, so for development, the environment has to be set up for `dist` as well.

Note: running `vendor/bin/phpunit` from root will result in using MyCMS classes from the root Classes even from `mycms/dist/Test`. While running `vendor/bin/phpunit` from `dist` will result in using MyCMS classes from the `dist/vendor/workofstan/mycms/classes`.

GitHub Actions' version of PHPUnit uses config file [phpunit-github-actions.xml](phpunit-github-actions.xml) that ignores `Distribution Test Suite`because MySQLi environment isn't prepared (yet) and HTTP requests to self can't work in CLI only environment.

### Reusing workflows

[](#reusing-workflows)

As dist/.github/workflows [reuses](https://docs.github.com/en/actions/using-workflows/reusing-workflows) some .github/workflows through workflow\_call, it is imperative not to introduce ANY BREAKING CHANGES there. The reused workflow may be referenced by a branch, tag or commit and doesn't support [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

```
    # Working examples
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@main # ok, but all encompassing
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0.4.10 # it works

    # Failing examples
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@^v0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@^0.4
    uses: WorkOfStan/MyCMS/.github/workflows/phpcbf.yml@v0
```

Therefore, if a breaking change MUST be introduce, create another workflow to be reused instead of changing the existing one!

### PHPStan

[](#phpstan)

Till PHP&lt;7.1 is supported, neither `phpstan/phpstan-webmozart-assert` nor `rector/rector` can't be required-dev in composer.json. Therefore, to properly take into account Assert statements by PHPStan (relevant for level&gt;6), do a temporary (i.e. without commiting it to repository)

```
composer require --dev phpstan/phpstan-webmozart-assert --prefer-dist --no-progress
composer require --dev rector/rector --prefer-dist --no-progress
```

and use [conf/phpstan.webmozart-assert.neon](conf/phpstan.webmozart-assert.neon) to allow for `phpstan --configuration=conf/phpstan.webmozart-assert.neon analyse . --memory-limit 300M`.

Prepared scripts [./phpstan.sh](phpstan.sh)and [./phpstan-remove.sh](phpstan-remove.sh)can be used to start (or remove) the static analysis. (TODO: call the dist scripts from root to DRY.)

How does Friendly URL works within Controller
---------------------------------------------

[](#how-does-friendly-url-works-within-controller)

[SEO settings details including language management in `dist` folder](dist/README.md#seo)

```
new Controller(['requestUri' => $_SERVER['REQUEST_URI']])
│   // request URI is set in multiple places
│   ->requestUri
│   ->projectSpecific->requestUri
│   ->friendlyUrl->requestUri
│   ->friendlyUrl->projectSpecific->requestUri
│   ->result['template'] = TEMPLATE_DEFAULT
│
└───run()
│   └── $controller->MyCMS->template = $this->result['template'];
│   │
│   └───$controller->friendlyUrl
│       └── ->determineTemplate(['REQUEST_URI' => $this->requestUri]) // returns mixed string with name of the template when template determined, array with redir field when redirect, bool when default template SHOULD be used
│            ├── ->friendlyIdentifyRedirect(['REQUEST_URI' => $this->requestUri]) // returns mixed 1) bool (true) or 2) array with redir string field or 3) array with token string field and matches array field (see above)
│            │   ├──if $token === self::PAGE_NOT_FOUND
│            │   │    └──$this->MyCMS->template = self::TEMPLATE_NOT_FOUND
│             friendlyfyUrl(URL query) // returns string query key of parse_url, e.g  var1=12&var2=b
│                 │    │   └── ->switchParametric(`type`, `value`) // project specific request to database returns mixed null (do not change the output) or string (URL - friendly or parametric)
│                 │    │        └──If something new calculated, then
│             language != DEFAULT_LANGUAGE) // no language subpatern and the language isn't default
│              $this->requestUri], $token, $matches); //FRIENDLY URL & Redirect calculation where $token, $matches are expected from above
│                       ├──default scripts and language directories all result into the default template
│
