Released Version 2.2.0 to Break the Parkinson’s Law

Let’s see what has been changed in version 2.2.0 compared to version 2.0.0.

Table of Contents
  1. Pages on This Website
  2. Added More Static Functions
  3. Being More Generic
  4. From ‘Reset’ to ‘Let’
  5. Get Used with Closures
  6. Get Used with Null Coalescing Operator
  7. Get Used with Generators
  8. Removed Plugin Features
  9. Removed Language and Layout Switcher Features
  10. Removed Escape Syntax for Blocks
  11. Page Conditional Statements
  12. Default User Log System
  13. Configurable Comment Thread’s Depth
  14. Improved Search Functionality
  15. Minimalist Control Panel Layout
  16. The Task Feature
  17. Others

This started from a mistake: poor time management! After the release of version 2.0.0, I have never set a fixed deadline for the next release. I was just stunned at the presence of PHP 7.1.0 and wanted to use the new features as much as possible, and therefore made the completion time even longer. The development process feels nothing more than a mere experiment without considering the users’ needs. This led me to conclude that I was stuck with the Parkinson’s Law.

“Work expands so as to fill the time available for its completion.”

Entering this January of 2020, I have reached the point that this development process has taken too long to complete. Although I haven’t updated all of the official extensions and themes completely to make it work with the current core version, I am still determined to release this version today. The sooner the better.

Updates to other extensions and themes will follow along with the minor changes of the core if needed. Extensions and themes that are already compatible with this version will be displayed in the store section. You might also be interested in surfing to the new documentation pages, especially in the static function reference.

Apart from that, let me show you the changes that I have made in the current release…

Pages on This Website

I reverted some of the page status on this website to draft because some of the code in it was no longer compatible with the current version. I don’t want to confuse users who want to learn more. Maybe I will publish it again when I’m ready.

Added More Static Functions

I ventured to define some new static functions aside from functions that I named alphabetically from A to Z in the hope that this would speed up the operation process on certain tasks compared to when you use the class approach. I have documented all of these in details here.

Being More Generic

Class name like Union is no longer suitable for Mecha as it will make it more difficult for users to recognize its function by its name. The name SGML is more generic and so will be straight to the point. I also have removed some classes that don’t offer any advantages other than “fashion” like … the Form class.

Why? Becuase at first, I thought it would be good for developers if I give them some helper methods like Form::text() and Form::textarea() to speed up the creation of form elements. But, when I try to portray myself as a developer, to use the API of this class requires me to learn through the documentation page just to create a HTML <input type="text"> element. That makes the process of achieving the goal twice as long. So, I decided to make everything conventional, back to the manual method, that is, by letting them write HTML elements manually using their hands, without any PHP processing help. Advanced HTML form elements API can be created as separate extensions, with third-party PHP libraries if necessary.

Mecha also tries to avoid new syntaxes that are rarely known to be used, especially for patterns within string data. Mecha tries to maintain the generic syntax of PHP, printf, XML, JSON and YAML (or trying to make a parser for similar pattern if necessary) so that it will be more easily understood by everyone.

From ‘Reset’ to ‘Let’

The “Set, Get and Reset” method naming standard that I have described earlier in this article has now been changed to “Set, Get and Let”:

Session::set('foo', 1);
Session::get('foo'); // `1`
Session::let('foo');

Session::get('foo'); // `null`

Get Used with Closures

Now you can call page properties via $this property inside the hook function, either as a named function or as an anonymous function:

function hook_1($content) {
    if ($this->foo) {
        return strtr($content, [':)' => '&#x1f60a;']);
    }
    return $content;
}

Hook::set('page.content', 'hook_1');
Hook::set('page.content', function ($content) {
    if ($this->foo) {
        return strtr($content, [':(' => '&#x1f641;']);
    }
    return $content;
});

Get Used with Null Coalescing Operator

Several methods used to obtain data such as Session::get($key, $fail = false) previously will always be accompanied by an extra parameter ($fail in this case) to declare an alternative value that will be returned if the desired data does not exist:

// Return the `foo` value or `0`
Session::get('foo', 0);

But, as the so called “null coalescing operator” feature in the latest PHP version becomes so useful that it can simplify some API that requires more function parameters in the previous versions, this inspired me to use null value everywhere as the default value for all inaccessible data. From now on, use the ?? operator to determine alternative value:

// Return the `foo` value or `0`
Session::get('foo') ?? 0;

Get Used with Generators

We no longer load the pages data as a plain list of page instances. A page list will now be a generator where there will only be a list of page path as a reference for each generator item. Page data will be loaded only if you iterate over the generator. So, as long as the page list is not iterated, the page data for each item will never be loaded:

$pages = Pages::from(LOT . DS . 'page');

test($pages);

foreach ($pages as $page) {
    test($page instanceof Page);
}

Removed Plugin Features

I have removed the ambiguity between what the extension is and what the plugin is. All plugins can now be placed along with the extensions, in the .\lot\x folder. There are no such thing called “plugin” in version 2.2.0. They are now simply called “extension”.

Removed Language and Layout Switcher Features

Have been struggling with multi-language features before. Until now, I can only concluded that human language is one part in a programming language that can never be structured. And so, back to basics! Now we simply have an untouched multi-language feature. At first, they were all be written in plain English words and phrases. Then, you will have an access to change the language text without touching the layout files, through a function. You can learn more about the internationalization function here.

Languages is one part of a website that seems to be very rarely changed after a website has been officially launched. And so I decided to remove the user language modifier feature in this version.

I also have removed the theme modifier feature for the same reason. Now we no longer have the ability to change themes through configuration files, and therefore there will only be one theme on every website built with Mecha. As with the site’s interface language, themes are one of the things that website owners rarely change within a daily or monthly period. So, I decided to remove such features.

Layout files are stored in the .\lot\layout folder. To change the default theme with another theme, remove all files from that folder and then put your custom theme files there.

Removed Escape Syntax for Blocks

We no longer provide special syntax to display block markup as-is within the page content. Use your creativity to make it. The easiest way would be to use HTML entities in place of writing the literal [ and ] characters:

<!-- Method 1 -->
&#x5B;&#x5B;foo-bar&#x5D;&#x5D;

<!-- Method 2 -->
[<span>[foo-bar]</span>]

<!-- Method 3 (not copy-paste friendly) -->
[&zwnj;[foo-bar]&zwnj;]

Page Conditional Statements

The page conditional statement feature is now available for layouts. All state data stored in key are, can, has, is and not will make the page condition becomes true as long as the value in it cannot be evaluated to false. All statements below are correct to declare a page conditional statement check:

if ($site->get('is.page')) { … }
if ($site->is('page')) { … } // Preferred
if ($state->get('is.page')) { … }
if ($state->is('page')) { … } // Preferred
if (Site::get('is.page')) { … }
if (Site::is('page')) { … } // Preferred
if (State::get('is.page')) { … }
if (State::is('page')) { … } // Preferred

This feature also adds special classes to the root element as long as you have class attribute on it. For example, if you have true condition for is.art and is.page, then class is:art and is:page will be added to the root element like this:

<html class="is:art is:page">

You can use those classes to detect page conditional statements within the CSS rules and JavaScript commands, for example:

.is\:art article { … }
if (document.documentElement.classList.contains('is:art')) { … }

Default User Log System

Log-in and log-out system for users is now available as default functionality for user extension. You can log the user in or out even without the panel extension. User log system in our new panel extension now depends on this functionality.

Configurable Comment Thread’s Depth

The previous version only supports two comment thread levels. Now you can specify the depth level of comment replies through the configuration file in the comment extension. The current version also enables user button if you have installed the user extension. So you don’t need to fill in your name and e-mail address to publish a comment when you are logged in.

Improved Search Functionality

The search functionality now comes as a separate extension. With the presence of the stream function to read the file content line by line without using a lot of memory from the server, this allows us to search within the file content to improve the search function in the previous version which only searches for file names to maintain the site performance.

Minimalist Control Panel Layout

We have entered a trend where blogs only have one column layout. Mecha intentionally follows the minimalist trends to be applied to the new control panel look and feel. The new control panel display now has no sidebar and only consists of form elements in one column to help you focus on the content. FYI, this is one of the updates that made the current release version take so long because I needed to make it from scratch, including to redesign the layout system. I hope the results are satisfying:

Panel

See more previews on the control panel extension page →

The Task Feature

A PHP includable file that will be executed once. Read more here.

Others

There are various enhancements to the extensions, especially the control panel extension. I can’t explain them all in details here, you may find them out on the release page of each repository. Some extensions are still incomplete, and are no longer compatible with this version, as well as user requests that still cannot be fully realized. Don’t worry, I still remember them all and still working on it! Actually, I just need more time and coffee.

18 Comments

Anon

ada error: Parse error: syntax error, unexpected '?' in C:\xampp\htdocs\mecha\index.php on line 19

Di baris 19 ada token “null coalescing operator” yang hanya bisa dibaca oleh PHP versi 7.1.0 ke atas. Kalau muncul pesan kesalahan seperti itu kemungkinan adalah karena versi PHP yang kamu pakai berada di bawah spesifikasi minimal.

Anon

Terima kasih. Saya sudah perbarui.. Kalau untuk mengakses menu CMS-nya itu bagaimana? Jadi seperti Blogger, kita bisa mengunggah gambar, membuat tautan, gaya huruf dll (seperti yang ada di gambar tangkapan layar di media sosial @ta.tau.taufik).

Mecha sekarang sudah punya alat installer dasar, coba unduh di sini.

Untuk mengaktifkan fitur WYSIWYG bisa menggunakan ekstensi c-k-editor.4.

Anon

Untuk berkas installernya apakah semua extensi sudah terpasang di dalam?

    Installer cuma sebatas memasangkan core, ekstensi user sama panel saja. Jadi pengguna bisa langsung pakai fitur panel kontrol setelah proses pemasangan selesai. Untuk ke depannya mungkin fitur installer ekstensi dan layout akan tersedia di dalam kontrol panel itu sendiri. Jadi untuk proses pemasangan dan pelepasan pernak-pernik selanjutnya dapat dilakukan melalui halaman panel kontrol secara langsung.

      Anoon

      Bisa di-install di subdirectory 'public_html' gak ya? misalnya saya installnya di directory 'public_html/blog' bisa gak?

      Bisa kok.

      Kalau sudah diunggah ke public_html dengan benar harusnya nggak perlu mengakses lokasi berkas apa adanya sebagai URL publik. Semua berkas di bawah public_html normalnya dapat diakses setelah domain https://blog.anam.my.id. Mungkin peladen yang kamu punya nggak pakai Apache tapi Nginx?

      .\var\public_html\favicon.ico → https://blog.anam.my.id/favicon.ico

      Saya sudah baca sekilas. Itu sepertinya tugas akhir mahasiswa TI yang kebetulan tertarik dengan topik sistem manajemen konten berbasis berkas. Sudah cukup lama, harusnya Mecha yang dibahas di situ adalah Mecha versi 1.x.x. Versi 2.x.x performanya sudah meningkat jauh.

      Kalau mau lanjut ke pembahasan yang lebih mendalam, mas bisa manfaatkan fitur diskusi ini, supaya datanya nanti lebih teratur:

      https://github.com/mecha-cms/mecha/discussions

        Emde Fikri

        Halo Mas Taufik, saya ingin membedakan nilai tag title dan heading H1.

        ---
        title: How to Write a Markdown Content
        description: Using Markdown syntax in page title, description and content.
        title: Markdown Content
        author: Taufik Nurrohman
        type: Markdown
        ...

        Gimana caranya ya?

        Taufik Nurrohman

        Bikin aja bidang baru mas, namanya bebas. Misalnya title_h1

        ---
        title: How to Write a Markdown Content
        title_h1: Markdown Content
        ...

        Nanti nilainya bisa dipanggil melalui properti title_h1 seperti ini:

        <h1><?= $page->title_h1; ?></h1>

        Emde Fikri

        Kalau di Blogger kita bisa memanggil konten sebagai JSON dengan <data:post.body.jsonEscaped>. Bagaimana saya bisa memanggil konten Mecha untuk saya implementaskan ke dalam kepala HTML?

          Taufik Nurrohman

          Cek manual tentang kelas To. Nanti mas bisa nemu banyak fitur untuk konversi teks. Termasuk juga fitur untuk membuat konverter teks sendiri.

          <script type="application/ld+json">
          <?= To::JSON([
              '@context' => 'https://schema.org',
              '@type' => 'NewsArticle',
              'mainEntityOfPage' => [
                  '@type' => 'WebPage',
                  '@id' => $page->url
               ],
               'headline' => $page->title,
               'image' => $page->images,
               'datePublished' => $page->time->format('c'),
               'dateModified' => date('c', filemtime($page->path)),
               'author' => [
                   '@type' => 'Person',
                   'name' => (string) $page->author
               ],
               'publisher' => [
                   '@type' => 'Organization',
                   'name' => $site->title,
                   'logo' => [
                       '@type' => 'ImageObject',
                       'url' => $url . '/favicon.ico'
                   ]
              ]
          ]); ?>
          </script>

            Emde Fikri

            Matur suwun Mas, saya akan coba baca semua dokumentasi Mecha.

            Tapi kalau saya enggak paham, nanti tetap kembali tanya-tanya kepada sampean.

            Saya sangat menyukai Mecha yang ringan sekali.

            Hehe. Tanya lagi ini: ada dokumentasi untuk mengubah jalur url, Mas? Misalnya, lochalhost/article/foo menjadi localhost/foo.

            Saya masih belum paham kategori dan tag di Mecha. Saya baru saja buat folder baru di dalam folder page, bersanding dengan folder article bawaan Mecha. Dan ia tidak muncul di navigasi. Ketika saya akses localhost/blog/foo page not found.

            Rute kustom bisa dibuat tapi secara manual. Kurang lebih begini harusnya bisa:

            Route::set('foo', function() {
                Route::fire('*', ['article/foo']);
            });

            Cuma rute lama masih bisa diakses, jadi kurang efektif.

            Folder .\lot\page\blog saja tidak cukup mas, harus ada berkas halaman juga untuk menyatakan halaman blog sebagai .\lot\page\blog.page

            .\
            └── lot\
                └── page\
                    ├── blog\
                    └── blog.page