Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pico 1.0 #252

Merged
merged 120 commits into from
Nov 6, 2015
Merged

Pico 1.0 #252

merged 120 commits into from
Nov 6, 2015

Conversation

PhrozenByte
Copy link
Collaborator

First of all: Why? The sourcecode of existing forks like BaunCMS and PhilleCMS isn't "stupidly simple" anymore... You can read Picos sourcecode from top to down and even copy&paste programmers will understand what's going on. It's all about "understanding at first glance".

Most important second: All changes are 100% backward compatible.

I considered writing something own, but then caught up with Pico. The only thing missing was clean code - Picos concept, workflow and code really is "stupidly simple", but very powerful. Actually I just did a code refactoring. I don't want to fork Pico and I won't do it even if you reject my changes (obviously I'll still use it myself 😄).

This should be v1.0 ready. I recommend to release it as v1.0-beta, waiting some weeks to test it on a large user basis (I'll fix all appearing problems) and finally releasing it as Pico 1.0 😄

Please give me a hint if you'll merge this, I'll then update the homepage (gh-pages branch), changelog.txt etc. accordingly.

What did I do?

  • Fixes Make apache mod_rewrite optional (default: on) #79, Closes [question] why do you call parse_content for each page in get_pages? #93, Fixes Content filenames containing spaces not working #99, Closes behavior of file path definition on file inexistance rather than directory existance #103, Closes Parse the file meta using the Symfony2 YAML Component. #116, Fixes Titles used as page identifiers #140, Fixes Performance on large number of pages #158, Closes Is there a way to make one plugin require another? #171, Fixes Get content file filename #210, Closes Bug fix : If the article of the same "title" there are a plurality , I show the "current_page" is different article file. #241, Closes Use scandir instead of opendir to ensure alphabetical order. #244, Closes Cleanup paths #246, Fixes First time clone and localhost Pico: Bunches of warnings #248, Fixes Allow .twig as file extension for templates #249, Fixes Incorrect versioning in file pico.php and config.php.template #250, Fixes Issues with URLs and loading files #251, Fixes Problem with HTTPS #253, Fixes PHP Built-in web server start command #257, Fixes Mod rewrite rules ignored #267
  • The code is now documented, code styling follows PSR. Pico superficially grows from 400 LoC to 1000 LoC, when removing all comments, Pico grows from 300 LoC to 500 LoC, mostly because of new public getter and helper methods (= 100 LoC) and PSR code styling. As said, there are no big functional changes, it's more a code refactoring.
  • The new routing system now works out-of-the-box (even without rewriting) with any webserver using the QUERY_STRING routing method. Internal links now look like ?sub/page, rewriting to basically remove the ? is still possible and recommended. Contrary to Pico 0.9 every webserver should work just fine. Pico 0.9 required working URL rewriting, so if you want to use old plugins/themes/contents, a working rewrite setup may still be required. If you're not using the default .htaccess, you must update your rewrite rules to follow the new principles. Internal links in content files are declared with %base_url%?sub/page. Internal links in templates should be declared using the new link filter (e.g. {{ "sub/page"|link }}), what basically calls Pico::getPageUrl(). You musn't change anything if you setup rewriting (what was required in Pico 0.9...), so I assume this to be fully backward compatible 😄
  • I've implemented a whole new plugin system while maintaining full backward compatibility. See the class docs of IPicoPlugin for details. The new event system supports plugin dependencies as well as some new events. It was necessary to reliably distinct between old and new events, so all events were renamed. The new PicoDeprecated plugin is crucial for backward compatibility, it's enabled on demand. Refer to its class docs for details.
  • I completely overhauled the sorting algorithms, so sorting by date now works as expected by using timestamps and index files are listed before their sub pages (so e.g. sub/index.md is listed before sub/foo.md).
  • Inaccessible files (like sub.md while sub/index.md exists) are now excluded from the pages list.
  • Now supporting per-directory 404.md files (if there is a sub/404.md, this file is displayed in favour of the global 404.md file, when e.g. the non-existing sub/notexisting.md is requested)
  • The file extension of content files is now configurable.
  • Heads up! Performance on large number of pages #158 is fixed only when the PicoParsePagesContent plugin isn't enabled. It's disabled by default, but gets automatically enabled with PicoDeprecated as soon as an old plugin is loaded. This is necessary to maintain backward compatibility. You can still disable it manually by executing $pico->getPlugin('PicoParsePagesContent')->setEnabled(false); or adding $config['PicoParsePagesContent.enabled'] = false; to your config.php.
  • The meta headers are now parsed by the YAML component of the Symfony project (see Parse the file meta using the Symfony2 YAML Component. #116) and it isn't necessary to register new headers during the onMetaHeaders event anymore. The implicit availability of headers is supposed to be used by users and pure (!) theme developers only, so we're still instructing plugin developers to register their headers. See the commit message of 7537159 for more detail.
  • Meta header variables are now accessible in content files using %meta.*%, so you mustn't repeat yourself. You can now put an excerpt into the description meta variable and output the same content at the beginning of the article using %meta.description% (see index.md for a example).
  • Initialization of Pico now works completely different: rather than defining constants (which are probably conflicting with other applications...), Pico now expects its paths to be passed as parameters to the constructor. The constructor doesn't start Picos processing anymore, you now have to call the Pico::run() method, which returns the parsed page contents instead of directly echoing them. The PicoDeprecated plugin defines the now deprecated constants ROOT_DIR, LIB_DIR etc., so old plugins can still use them. Those constants are defined before reading config.php in Picos root folder, so upgrading users usually aren't bothered with e.g. a PHP Notice: Use of undefined constant ROOT_DIR - assumed 'ROOT_DIR' error when using ROOT_DIR in their config.php (so: no BC break). New users don't need the constants anymore, relative paths are now always interpreted to be relative to Picos root dir, so $config['content_dir'] = 'content'; is always sufficient (previously this was depending on the webserver config). All these changes are supposed to improve Picos interoperability with other applications and allows developers to integrate Pico in other applications, therefore I additionally added a new Pico::setConfig() method to even make the use of a config.php optional.
  • The Twig cache dir doesn't exist anymore. The provided directory never was helpful, in most cases one still had to make the directory writable for the webserver, so it never worked out-of-the-box.
  • All index.html files were removed; instead of helping users to secure their website, they create a false sense of security. This leads to situations like "I'm receiving a empty website when navigating to the content folder, thus everything must be safe!"
  • I decided explicitly to NOT implement pages as objects ("stupidly simple", see above). Anyway, I think plugin developers shouldn't manipulate data in "wrong" events, this could lead us to unexpected behaviour. Sure, plugin developers still can do this, we're passing variables by reference, but it's not that obvious. I even thought about dereferencing the values after the corrosponding event was called, but that would be backward incompatible. What do you think?
  • How to fix the "composer problem" discussed in Pico v0.9 and beyond.... #221 and PICO v.9 #223? There's a very simple solution: When creating a release on GitHub (after you've pushed the tag) you can upload "binaries". Simply execute composer locally, create a ZIP archive and upload the result as "binary".
  • I didn't care much about Allow parse content using Twig (.html files). #110, Create pico_markdown.php #238, Create pico_twig.php #239 and Decouple Markdown and Twig #240 because I simply don't need these features. But I think they are good ideas and the core should support this. Just my 2 cents 😄
  • Nested pages variable #201 and Crop Images plugin #231 should be closed - this can easily be achieved with plugins. In fact, there are already plugins adding support for these features...
  • Imo distinct documentations for users, theme designers and plugin devs is MUCH more important than unit tests... Pico is a project with just about 500 LoC (+ comments), such a manageable project doesn't necessarily require unit tests - they are nice to have, but that's it. Documentation should be the top priority!
  • Note: I'm no english native speaker. Maybe someone should look through my code comments 😄

A empty index.html is a solution for nothing...
I unfortunately messed up my repo so this is just a single commit... :(
The plugin magic takes place here...
DummyPlugin is a template for Pico plugins. You're a plugin developer? This template may be helpful :-)
These plugins are crucial for backward compatibility
@theshka
Copy link
Collaborator

theshka commented Aug 30, 2015

Great work! I would definitely like to push this upstream-- it's so fresh, so clean 👍

Just a couple small problems to fix straight away:

In global.php there's some funky paths still set to your environment; replacing the first two lines, and THEMES_DIR path does the trick:

//define('HTTPDOCS', realpath(rtrim(__DIR__, '/')) . '/');
//define('ROOT_DIR', realpath(HTTPDOCS . '../httpdocs-includes') . '/');
define('ROOT_DIR', realpath(rtrim(__DIR__, '/')) . '/');

//define('THEMES_DIR', HTTPDOCS . 'themes/');
define('THEMES_DIR', ROOT_DIR . 'themes/');

and line 377 of pico.php throws a NOTICE when $_SERVER['QUERY_STRING'] is null.

//$pathComponent = $_SERVER['QUERY_STRING'];
$pathComponent = (isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '');

I'd like to get some more input, anyone else still following Pico??

@PhrozenByte
Copy link
Collaborator Author

Oops, that was the wrong global.php 😄
Sure, it's a good idea to wait for about 1-2 weeks to get a little more feedback before merging this, it's a quite big update

@stefanbohacek
Copy link

When ordering posts by date, would it make more sense to use something like this?

  if ($order_by == 'date' && isset($page_meta['date'])) {
      $sorted_pages[$page_meta['date_formatted'] . $date_id] = $data;
      $date_id++;
  } else {

Currently it's this.

      $sorted_pages[$page_meta['date'] . $date_id] = $data;

This seems to be the only thing that works for me, as I'm using the date format of MMMM DD, YYYY (eg August 31, 2015).

@PhrozenByte
Copy link
Collaborator Author

I'm not really sure what you mean. In this PR posts aren't sorted by the Date meta header directly, instead they are sorted by $data['time'], the timestamp resulting from a strtotime() call. What sorting would you expect?

@stefanbohacek
Copy link

@PhrozenByte

Well, if you go to https://botwiki.org/tag/twitterbot, the posts are now correctly ordered while using the MMMM DD, YYYY format (see this for an example).

If I go back to using $page_meta['date'] for sorting, it seems almost random.

Feel free to clone https://github.com/botwiki/botwiki.org and play with it locally.

@PontusHorn
Copy link

This looks great to me. Would be more than happy to see it merged.

@fourtonfish, have you looked through the changes in the PR? The code you're referring to isn't used anymore in it. Your problem, as I understand it, is already fixed here.

@stefanbohacek
Copy link

@PontusHorn Ah, my bad, I think I only looked at the most current stable, not this PR.

Well, great job, then :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment