Split Source into multiple files during development and merge with Build script

Issue #190 resolved
Christopher Kramer created an issue

Originally reported on Google Code with ID 190

Currently we develop PLA in one file. The one-file approach is good for the release
(install, deployment...), but bad for development. It can lead to lots of unnecessary
merging. And by splitting the code into several files, it would be easier to find the
relevant parts in the code etc.

So I would propose something like this for a start:

- phpliteadmin.php: Everything currently in there, except:
- defaulttheme.css: Default JS theme
- script.js: JavaScript. Possibly splitted into multiple files.
- favicon.ico: The favicon
- One file per (PHP) Class

This should be good start. the goal should be to move more and more code out of the
phpliteadmin.php into Classes.

Then we need a build-script that automatically bundles everything into one phplteadmin.php
file again that we can release.
This build script would more or less only paste the individual file data inside the
phpliteadmin.php. Maybe do some compression of JS and CSS.

During development, it is important that PLA runs without the need to run the build
script every time.
So basically, I think in phpliteadmin.php, we move some stuff out and replace it with
include()s. The build-script then only replaces the include()s by the actual file content.

Reported by crazy4chrissi on 2013-03-09 00:38:48

Comments (59)

  1. Christopher Kramer reporter
    (this was mentioned as a comment in issue #157).
    

    Reported by crazy4chrissi on 2013-03-09 00:39:35

  2. Former user Account Deleted
    if i do it, i would do something like this (on image). templates would be in ob_start
    or somewhere at the end of file.
    
    So, everything will be in classes, while start up will look like
    
    Factory::getApp()->init(debug)->dispatch();
    or
    Factory::getApp()->init(debug)->route()->dispatch();
    

    Reported by ykorotia on 2013-03-09 18:17:13

    <hr> * Attachment: schema.jpg

  3. Christopher Kramer reporter
    This issue is not about improving the architecture of PLA, it is about splitting files
    to simplify development. Or to rephrase it: It is not about restructuring or changing
    any code. It is about splitting the code that is already existing. Improving the development
    infrastructure, not PLA itself.
    
    Restructuring, like introducing an MVC architecture, as implied by your draft, is another
    issue. Although this could largely benefit from this issue (being infrastructure that
    supports restructuring).
    

    Reported by crazy4chrissi on 2013-03-09 18:25:35

  4. Christopher Kramer reporter
    SQLite itself also is developed in lots of files (of course ;-)) - see https://www.sqlite.org/cgi/src/dir?ci=e899b058a7031580&name=src
    ) and then the make script builds one big file out of it. See https://www.sqlite.org/amalgamation.html
    .
    

    Reported by crazy4chrissi on 2013-03-09 18:40:39

  5. Former user Account Deleted
    I see. But you already do it with version 2, right? Or version 2 is dead?
    
    for better merging you have to remove duplicates of code and remove global variables,
    otherwise, it will be hard to get what variable is set and where.
    
    it is not mvc, your structure is simple, so I suggest to extend your app with configuration
    and registry classes. factory is also good.
    
    also many methods have many if-else, it is very hard to read (for me), but if it is
    good for you, nevermind then. Still I'm somewhere on line 900.. so don't get me too
    serious
    

    Reported by ykorotia on 2013-03-09 18:42:56

  6. Former user Account Deleted
    about merge script, it can be like this
    
    MERGE.bat
    copy test1.txt+test2.txt test3.txt
    

    Reported by ykorotia on 2013-03-09 18:48:38

  7. Christopher Kramer reporter
    >  Still I'm somewhere on line 900.. so don't get me too serious
    lol. I have never read the code like this.
    
    > I see. But you already do it with version 2, right? Or version 2 is dead?
    This was planned for version 2, but nobody currently develops version 2, so I think
    it won't every come to live. Instead we incrementally improve the current version until
    we have what was planned for version 2. One of these steps is to split files. For version
    2, the build-process was not implemented yet, so we cannot use anything from there.
    
    > for better merging you have to remove duplicates of code and remove global
    > variables, otherwise, it will be hard to get what variable is set and where.
    I am not sure what you mean. I plan to only move classes out of the phpliteadmin-file.
    So there should be almost no global stuff used in there.
    

    Reported by crazy4chrissi on 2013-03-09 18:51:08

  8. Christopher Kramer reporter
    > MERGE.bat
    > copy test1.txt+test2.txt test3.txt
    
    No, that is not what I have in mind. The problem with this would be that you could
    not run PLA without running merge.bat after every change. This would make development
    harder (more annoying / requiring better IDEs).
    
    Instead, look at this example:
    phpliteadmin.php:
    <?php
    
    ...
    
    #INCLUDE
    include('classes/Authorisation.class.php');
    
    ..
    ?>
    
    So we can run phpliteadmin.php during development without the need to run the build-script.
    
    Then we have a buildscript that replaces the include() marked by the #INCLUDE marker
    with the file referred to.
    I think for portability, we should best implement this in php. A windows batch file
    or linux make file does not run on both platforms, so we would need to write and maintain
    2 of them.
    
    I thought of something like:
    build.php
    <?php
    
    $source=file_get_contents('phpliteadmin.php');
    preg_match_all('/#INCLUDE\n\s*include\(\'([^\']+)\'\);/',$source,$matches);
    foreach($matches as $match) {
     $include_source = file_get_contents($match[1]);
     $source = str_replace($match,$include_source,$source);
    }
    file_put_contents('built/phpliteadmin.php');
    ?>
    
    (just a draft to illustrate what I mean, not tested etc)
    

    Reported by crazy4chrissi on 2013-03-09 19:06:32

  9. Former user Account Deleted
    bat is enough to make bulk file, you can add/update bulk file in svn.
    For developer it is enough to have entry point like index.php which won't be included
    by bat file.
    about linux, it is simple as is
    $cat test1.txt test2.txt >> test3.txt
    
    i guess, you will have to have merged file in svn too. or you don't want to keep this
    file in repository?
    
    you can merge with php, the main question is - who will merge files?
    

    Reported by ykorotia on 2013-03-09 19:37:28

  10. Christopher Kramer reporter
    Hmm. Well, yes, we could have an index.php that includes all other files to run PLA
    during development like this:
    
    index.php
    <?php
    include('file1.php');
    include('file2.css');
    include('file3.js');
    include('file4.php');
    ...
    ?>
    
    We would need to make sure links work (i.e. point to the correct php-file) then, but
    this would be easy. And we could have a batch script for linux and windows to concat
    these files like your examples.
    But:
    We specify the list of files to include in 3 places then: the index.php, the windows
    build script and the linux build script. This can get inconsistent easily.
    
    That's comparably easy to fix, all 3 scripts could simply use all files form a certain
    directory automatically. But then, in which order? We would need to enumerate files.
    And then, what if we put a new file in between? rename all following files?
    
    Another way would be to have another central config-file for all 3 (build) scripts
    (like filelist.txt) that lists the files in the order to include them.
    
    But I think the solution of having normal php includes that get replaced by a build
    script still is a lot nicer and easier to figure out.
    
    > i guess, you will have to have merged file in svn too. or you don't want to keep
    > this file in repository?
    Good question. I guess we should not include it in the repository. The merged file
    is for the release. It would change with every commit or would be inconsistent with
    the other files.
    I think the best approach would be to setup a post commit web hook (which is supported
    by google code) that automatically runs the build script after every commit and makes
    the built file available on some webserver.
    
    This would allow us to always have a 1-file development version of PLA available. for
    example, I like to post links of the current development version to users so they can
    check if the bugfix works for them. It would not be so easy for them to checkout the
    whole source with multiple files.
    

    Reported by crazy4chrissi on 2013-03-09 20:36:00

  11. Christopher Kramer reporter
    By the way: As I mentioned, minifying files might be an additional task that could be
    performed by the build script. So compressing js/css files, maybe even the php-file
    itself.
    Would be better to have a central automatically running build script that does this
    than to have linux and windows batch scripts that do this.
    Minify is a cool php script for this for example ( https://code.google.com/p/minify/
    ),
    

    Reported by crazy4chrissi on 2013-03-09 20:50:25

  12. Former user Account Deleted
    what about next aproach: index.php?merge
    
    index.php
    <?php
    $files = array('file1.php', 'file2.php',...);
    
    if(isset('merge')) {
    $buf ='';
    foreach($files as $f) { $buf .= file_get_content($f); }
    file_put_content('pla.php', $buf);
    echo 'merged successfully';
    die;
    }
    
    foreach ($files as $f) { include  $f; }
    

    Reported by ykorotia on 2013-03-09 21:58:46

  13. Christopher Kramer reporter
    Hmm. That solves the problem of portability (by using php) and consistency (by using
    a single file-list).
    
    I think that approach is okay.
    But I still see a disadvantage. Example:
    
    file1.php
    <?php
    //part1
    //part2
    //part3
    ?>
    Now you want to move part2 into a separate file.
    Then you need to create 3 files, ripping apart part1 and part3, although they might
    belong together:
    
    file11.php <?php // part1 ?>
    file12.php <?php // part2 ?>
    file13.php <?php // part3 ?>
    
    With my approach, you could insert an include between part1 and part3 so they stay
    together.
    
    
    Any other opinions?
    

    Reported by crazy4chrissi on 2013-03-09 22:35:26 - Status changed: Accepted

  14. dreadnaut
    So much to read suddenly :)  A couple of sparse comments before I get to the point:
    - we have php, let's avoid shell or batch scripting
    - rather than include, this is a job for 'require'
    - include/require are not functions, no need for brackets
    
    That said, I wouldn't use either of them (kinda). It's 2013 and we've had class autoloading
    for some time, spl_autoload¹ starting from php 5.1.2, and PSR² stuff is looming.
    
    I'd like to split classes into separate files and autoload them (and yes, that requires
    'require's) and for release we simply concatenate the main file with the class files,
    without changing a line of code. The build script can be php and handle resource inclusion,
    minifying and encoding —so we can use php-minify instead of YUI Compressor.
    
    The split version and bundled version should live in parallel, to make switching from
    one to the other (that is, development) easier. I'd suggest this directory structure
    
    /-- (version directory)
      |
      +-- build-pla.php
      +-- index.php ( main pla script, non-oo code )
      +-- phpliteadmin.config.php ( personal, works for both versions, not in repo )
      +-- phpliteadmin.config.sample.php
      +-- phpliteadmin.php ( built by script )
      +-- resources/*  ( css/js/etc )
      `-- classes/*    ( ClassName.php )
    
    
    The easiest way to embedding resources would be to have some placeholders inside the
    code, but maybe we can work around that with a smarter Resources class.
    
    
    [1] http://www.php.net/spl_autoload
    [2] http://www.php-fig.org/
    

    Reported by dreadnaut on 2013-03-10 11:21:27

  15. dreadnaut
    I had a look at php minify, the script linked above, and I'm a bit uncertain. Of the
    whole package, we need only two classes (Minify_JS_ClosureCompiler and Minify_CSS_Compressor),
    but the first contacts an online service to compile javascript and will not work without
    an internet connection.
    
    I'll look around, hopefully there's a similar php solution with a self-contained implementation.
    

    Reported by dreadnaut on 2013-03-13 16:00:25

  16. dreadnaut
    I was just trying the split + autoload system now and a 5-lines function is enough to
    hold everything together.
    
    If you like the method I can prepare a patch and commit it first thing after we release
    1.9.4, so we can then work on the build script in parallel with other development.
    

    Reported by dreadnaut on 2013-03-14 00:52:51

  17. Christopher Kramer reporter
    Yes, autoload definitely seems to be the correct way to load classes, better than the
    other 2 approaches.
    I think this should be the first step, so yes, please prepare a patch.
    
    We then need to make sure it is easy to edit css & js while developing (for css it
    is already easy as we can set $themes to the css file and that's it. But for JS we
    need to do something similar.)
    
    > I had a look at php minify, the script linked above, and I'm a bit uncertain.
    Well. In my opinion, we could simply setup the build script on some webserver so it
    always automatically builds the current development version. Then we could always have
    a built 1-file-version available. Nobody would need to setup the build script anywhere
    else.
    Then it would be no problem if we only need a small portion of minify or if it requires
    an internet connection. But this also means we could use YUI compressor for example.
    I am not sure if minify uses this as well, but Google also offers a JS minify API:
    https://developers.google.com/closure/compiler/
    
    But if you find some great php class that does our job so we can create a small php
    build script that anybody can setup easily, of course this would be a lot better.
    
    When we are done with this issue, we should create a wiki page that explains some things
    on how to develop PLA most easily.
    

    Reported by crazy4chrissi on 2013-03-14 11:51:09

  18. Christopher Kramer reporter
    Ah. On another project, I was using these 2:
    http://code.google.com/p/cssmin/
    https://github.com/rgrove/jsmin-php/
    
    The later one is unmaintained and says "You shouldn't use it." ;-)
    (Nevertheless it worked great when I used it...)
    
    It recommends this one (and google closure I mentioned above):
    https://github.com/mishoo/UglifyJS2
    But this is not php, it is js (node.js).
    

    Reported by crazy4chrissi on 2013-03-14 11:57:34

  19. Christopher Kramer reporter
    Here are some more to check out:
    https://github.com/tedivm/JShrink (looks good at first sight)
    http://crisp.tweakblogs.net/blog/cat/716
    

    Reported by crazy4chrissi on 2013-03-14 12:05:13

  20. dreadnaut
    There a JSMin+ but I'm not sure of its status. I'll look around, but if we don't mind
    java the YUI Compressor might be one of the best solutions.
    
    About autoloading, this is what I tried:
    
    @@ -361,6 +361,20 @@
     define("FORCETYPE", false); //force the extension that will be used (set to false
    in almost all circumstances except debugging)
     define("SYSTEMPASSWORD", $password); // Makes things easier.
    
    +// setup class autoloading
    +function pla_autoload($classname)
    +{
    +   $classfile = __DIR__ . '/classes/' . $classname . '.php';
    +
    +    if (is_readable($classfile)) {
    +      include $classfile;
    +      return true;
    +    }
    +    return false;
    +}
    +
    +spl_autoload_register('pla_autoload');
    +
     // Resource output (css and javascript files)
     // we get out of the main code as soon as possible, without inizializing the session
     if (isset($_GET['resource'])) {
    

    Reported by dreadnaut on 2013-03-14 12:07:37

  21. Christopher Kramer reporter
    Yes, looks good. But didn't you say yourself that this is a job for require? ;-)
    

    Reported by crazy4chrissi on 2013-03-14 12:14:35

  22. dreadnaut
    Not in an autoloader :-p  If you can't find or load the file you should 
    not halt the script, but return false and let the next autoloader in the 
    chain try.
    

    Reported by dreadnaut on 2013-03-14 12:22:01

  23. Christopher Kramer reporter
    Okay, true. But as long as there is only one autoloader, it doesn't really make a difference,
    right? "Class not found" is a fatal error, so PHP will halt anyway if a class is missing
    (once used, and autoloaders don't get called if the class is not used).
    

    Reported by crazy4chrissi on 2013-03-14 12:28:39

  24. dreadnaut
    | But as long as there is only one autoloader, it doesn't really make a difference,
    right?
    
    Correct, it would be the same *if* there were only one autoloader. If someone integrates
    PLA with their software there might be more than one, so we shouldn't break the autoloading
    chain for no good reason.
    
    
    Attached is a sample split version so we have somewhere to start from. It uses Minify's
    CSS compressor class and JShrink for javascript (both stored inside the support/ directory).
    index.php contains the main code, while each class has its own source file under classes/.
    
    The build script concatenates the main index.php with classes/*.php, removing the first
    php opening tag. Resources are then prepared and replace any occurrences of :::filename:::
    in the source code. I modified the Resources class accordingly to work in split mode:
    if the resource data contains :::filename::: it will load the external file.
    

    Reported by dreadnaut on 2013-03-14 14:54:19 - Status changed: Started

    <hr> * Attachment: 1.9.5-test.zip

  25. dreadnaut
    New version, based on the code released for 1.9.4. Same changes as above: split classes,
    added autoloading (about line 390), added a basic build script.
    
    Should we place languages in a subdirectory? The root directory might get messy as
    we get more locale files, but we might also have to change some code to accomodate
    that. I think themes now do something similar, searching first in the current directory
    and the under themes/.
    

    Reported by dreadnaut on 2013-03-18 18:25:04

    <hr> * Attachment: 1.9.5-test.zip

  26. Christopher Kramer reporter
    Languages also get loaded from "languages". No problem to move them there. Works already.
    
    We should think about how we deal with the English stuff. Because I think it would
    be good to move this outside of the main file as well.
    
    (I have not had a look at your upload yet, will do so in a minute)
    

    Reported by crazy4chrissi on 2013-03-18 18:28:44

  27. Christopher Kramer reporter
    Looks like a very good start. I really like the Resource handling.
    It introduces 3 LOC that are useless in the build version, but that's clearly worth
    it.
    
    I would do the replacement of resources only on the code of the Resource class. Otherwise
    we introduce assumptions like "you must not have :::resources/phpliteadmin.css::: anywhere
    in your code". Although this assumption is quite safe, I would prefer to restrict it
    to the Resource class.
    
    About the <?php removal: I was thinking about whether it would be better to simply
    add ?> at the end of every php file. Then concatenation would work without removing
    "<?php". On the other hand, some useless "?>\n<?php" will end up in the code. Maybe
    your solution is better.
    
    As said before, I would prefer to move the English language definition out of index.php
    as well. At the moment we have it in 2 places, which can lead to redundancy problems.
    We could either implement something special in the Build-Script or change the language
    system somehow so it is a class that gets autoloaded to achieve that.
    
    When I look at what remains in index.php, this looks like quite a lot of work until
    we get this "nice".
    
    We should remove or adjust the #eof comment because with the build script it ends up
    in the middle of the file ;-)
    

    Reported by crazy4chrissi on 2013-03-18 18:54:46

  28. dreadnaut
    Closing php tags are a risk, you might end up sending a couple of newlines to output.
    With autoloading, files are included on the fly when you try to instantiate a class,
    which means that those newlines might end up in output before headers. Bugs waiting
    to happen IMO :)   Saying "the first line of a class file must be <?php" is a tame
    requirement in the end. The same for "class files should produce no output on loading."
    
    I'm uncertain about the Resource implementation, and I'll see if I can do better using
    __halt_compiler()¹. The current code mixes code and data too much, and would not scale
    well. That would also solve the :::something::: replacement in other parts of the code.
    
    English strings: good idea, although we can do that later. Let's split the source as
    soon as possible, as it will make working on multiple changes easier.
    
    | We should remove or adjust the #eof comment because with the build script it ends
    | up in the middle of the file ;-)
    
    Ah, yes! Maybe replace it with #main-code-ends-here, or just drop it.
    
    [1] http://php.net/manual/en/function.halt-compiler.php
    

    Reported by dreadnaut on 2013-03-18 23:18:16

  29. Christopher Kramer reporter
    | Closing php tags are a risk, you might end up sending a couple of newlines to output.
    Ah, right. Although you can end a file without a newline (and thus concatenate files
    without introducing one), some editors tend to add newlines at the eof, so your solution
    really seems to be safer.
    
    | I'll see if I can do better using __halt_compiler()
    I did not know this one. In the end it is only an "exit;" with the advantage that you
    can easily jump to __COMPILER_HALT_OFFSET__ and don't have to determine the position
    yourself. But looks very suitable in our case.
    
    | English strings: good idea, although we can do that later.
    Okay.
    
    | Maybe replace it with #main-code-ends-here, or just drop it.
    I think a comment like this might be useful (e.g. to search for the position).
    
    | I'm on it anyway, taking ownership :)
    Thanks.
    

    Reported by crazy4chrissi on 2013-03-19 17:07:55

  30. dreadnaut
    Ok, here's a different take on resources AND building.
    
    As I wrote above I am switching to __halt_compiler(), not only works as 'exit', but
    because whatever follows it is *completely ignored*: not parsed, not sent to output,
    nothing. You can have megabytes of binary madness after the call, and they won't affect
    the execution.
    
    This however makes the build script a bit more complicated, so I've added an external
    "build template" which contains directives to include the right files in the right
    position. Check 'build.php' for more details, I spent some time document the script
    so it's not black magic.
    
    A few changes to the Resources class as well, which now calls getInternalResource()
    to load data from the script file itself. It's not the *cleanest* implementation, but
    I think better than the previous version.
    

    Reported by dreadnaut on 2013-03-19 19:23:44

    <hr> * Attachment: 1.9.5-test-b.zip

  31. dreadnaut
    Sorry, there was a duplicated line in classes/Resources.php (line 53) which broke split-file
    execution. Attached is the correct file.
    

    Reported by dreadnaut on 2013-03-20 14:28:35

    <hr> * Attachment: Resources.php

  32. Christopher Kramer reporter
    Just had a look t your new solution "b". Looks very cool. I consider this more or less
    an advanced version of what I had initially in mind. Very flexible.
    
    What I noticed is that in the build script, you always work on $output. This means
    in case any of the files you put in $output contains some build-command interpreted
    next, it will get replaced.
    This means for example that #EMBED commands could also be placed inside of index.php
    or classes (but not #INCLDUE commands). I am still thinking about whether this can
    be useful or if it is rather dangerous.
    (As resources get base64 encoded, no build-command can accidentally get introduced
    in there as they require "# " which cannot be base64. )
    
    If we could also put #INCLUDE commands in the index.php, this would mean we could include
    lang_en.php this way. But then we could also put everything in index.php and wouldn't
    need the template...
    
    But I mean in the end, this is also a suitable solution that we could use and improve
    over time.
    

    Reported by crazy4chrissi on 2013-03-20 17:26:57

  33. dreadnaut
    Great feedback, thanks Chris. I am indeed following your first post :)
    
    Regarding working on $output, that's a good point, I missed it. We can work around
    it by first processing EMBEDs first and INCLUDEs second, though. I'd rather not have
    #EMBED commands appearing in other files: code in one place, data in another.
    
    A first version of the build script didn't use an external template and the directives
    were all at the bottom of index.php. It felt a bit dirty, so I switched to a separate
    file.
    
    We could #INCLUDE the english translation as default. At that point the external template
    cannot be used though, since the lang data must appear toward the top of the file —unless
    we also separate the license text and the default config (oh, wait we already do the
    latter!)
    
    I see two alternatives then:
    a) everything in index.php
    b) split more!
    
    In (b) we end up with a template more or less like this:
    
    <?php
    #INCLUDE docs/header.txt | comment_the_whole_thing
    #INCLUDE phpliteadmin.config.sample.php
    #INCLUDE languages/lang_en.php
    #INCLUDE index.php
    
    // resource embedding code
    function getInternalResource($res)
    {
      ...
    }
    
    #EMBED resources/*
    [...]
    
    I like including the default config, although this brings back some of the code and
    comments we removed when we added the sample config.
    

    Reported by dreadnaut on 2013-03-20 21:17:44

  34. Christopher Kramer reporter
    I also like b)
    More splitting is fine as long as we don't introduce too much coupling of different
    files.
    Splitting everything out of the main file that is "a thing of its own" is good.
    And default-config and the header comments can really be considered a "thing of its
    own".
    Aside: Thinking about the header: We could replace the manually updated "last updated"
    comment in the header with a date inserted by the build-script.
    #INCLUDE docs/header.txt | insert_build_date | comment_the_whole_thing
    
    > I like including the default config, although this brings back some of the code 
    > and comments we removed when we added the sample config.
    Well, the very good point of it is that we reduce redundancy. If we add another config
    variable, adding it to one file would be enough (at the moment, we'd need to add it
    in 2 files).
    About the comments and code: Well, I don't mind much about this. But if we want to,
    we can also make our build script smart enough to remove some lines (marked somehow?).
    #INCLUDE languages/lang_en.php | remove_marked_lines
    

    Reported by crazy4chrissi on 2013-03-20 22:06:55

  35. Christopher Kramer reporter
    Last line was meant to be:
    #INCLUDE phpliteadmin.config.sample.php | remove_marked_lines
    

    Reported by crazy4chrissi on 2013-03-20 22:08:57

  36. dreadnaut
    Currently, the build script remove all single-line comments starting with # (rather
    than //), even if they are not directives. I used it to add "build comments" here and
    there but is not essential to my implementation.
    
    We can make it a convention and use it to remove lines. Otherwise, we can strip lines
    between to special comments, e.g.:
    
    # IGNORE
    function should_not_be_in_the_single_file_code()
    {
      ...
    }
    # END IGNORE
    
    
    Last updated: I'd like to automate that and add it only to release and RC versions.
    I always forget to update it, and it will be even more difficult after the split, since
    we would have to commit at least two files every time!
    

    Reported by dreadnaut on 2013-03-20 22:55:54

  37. dreadnaut
    I've had a look at implementing comment #37 and building works alright. However, we
    need to include the default configuration otherwise for the split-file version to run
    :|
    
    Something like this would work, but maybe there's a nicer way.
    
    # IGNORE
    include 'phpliteadmin.config.sample.php';
    # END IGNORE
    
    
    Also, following Issue #197 and Lonnie's email* pointing out that we cannot give zlib
    for granted, I'm going to remove gzencoding from the build script.
    
    [*] https://groups.google.com/d/msg/phpliteadmin/gipdRoGVkjo/VIntw7P7cF0J
    

    Reported by dreadnaut on 2013-03-21 15:38:43

  38. dreadnaut
    Sorry, link to the wrong message, here's the correct one:
    https://groups.google.com/d/msg/phpliteadmin/gipdRoGVkjo/H8WevWOmUqkJ
    

    Reported by dreadnaut on 2013-03-21 15:39:41

  39. Christopher Kramer reporter
    > Something like this would work, but maybe there's a nicer way.
    Hmm. We could do something like this, but I think it's not better than your solution:
    
    if(!isset($databases))
      // can only happen in split-mode, as the built version defines it
      include 'phpliteadmin.config.sample.php';
    
    But the #IGNORE build-command could be useful anyway I think.
    
    > we cannot give zlib for granted, I'm going to remove gzencoding from the build script
    Yes. Zlib is always built-in on Windows, but not on Linux where you need to compile
    php with zlib and this is not the default. See http://www.php.net/manual/en/zlib.installation.php
    So we should not rely on it. If we use it, we first need to make sure it's available.
    But as the use is not important in this case, we probably better shouldn't use it at
    all.
    

    Reported by crazy4chrissi on 2013-03-21 15:50:29

  40. dreadnaut
    I'll go for an "#IGNORE" syntax then. Although... do you have any suggestions for a
    better keyword?
    
    #SPLIT-ONLY, #DON'T-BUILD, #BUILD:NO, #DEVEL —I can't find a good one :|
    
    
    For reference: we can use extension_loaded('zlib') to check for support.
    http://www.php.net/extension_loaded
    

    Reported by dreadnaut on 2013-03-21 15:59:46

  41. Christopher Kramer reporter
    Hmm. This command will make it not only in the template, but in the index.php. So some
    guys hacking pla might see it and we should give it a name so they know what's going
    on.
    My suggestion:
    # REMOVE-FROM-BUILD
    ...
    # END REMOVE-FROM-BUILD
    

    Reported by crazy4chrissi on 2013-03-21 16:36:55

  42. dreadnaut
    Ooook, maybe we are getting there. Here's version -C-.
    
    - added # REMOVE_FROM_BUILD ... # END REMOVE_FROM_BUILD build directive to ignore lines,
    available both in the build template and in included files;
    - added ###identifier### build directive to be replace with the content of a variable,
    available in all files.
    
    The former is used to include the default files in split-mode, and the latter is used
    to insert $build_date in header.txt. Maybe ###[\w+]### is not "safe" enough?
    
    - new build template that includes docs/header.txt, the sample config file and the
    English strings;
    - removed zlib compression, resources are now only minified;
    - swapped EMBED and INCLUDE to avoid embedding resources in included files; EMBED should
    now work only in the build template;
    - added comment_lines filter to comment header.txt.
    

    Reported by dreadnaut on 2013-03-21 19:15:46

    <hr> * Attachment: 1.9.5-test-c.zip

  43. Christopher Kramer reporter
    Thanks!
    > added # REMOVE_FROM_BUILD ... # END REMOVE_FROM_BUILD build directive to ignore 
    > lines, available both in the build template and in included files;
    Hmm. Does this make any sense in the build template? It will only be used when building.
    Having something in there that is removed while building is a bit weird. Well, it's
    some kind of multiline-comment, okay. (I know, it is easier to do it this way, and
    as it doesn't introduce any problems, it's perfectly fine.)
    
    >  Maybe ###[\w+]### is not "safe" enough?
    Hmm. If the build-script acted as documented in the comments, I'd say it is safe enough:
    // ###identifier###
    // Is replaced with the value of the variable $identifier, if defined
    
    "if defined" is not what the script does. If I append ###bla### to header.txt, it will
    get removed in phpliteadmin.php (i.e. replaced by nothing). Instead the build script
    should look up if the variable is set and skip ###bla### because $bla is undefined.
    
    If it acted like this, I would consider it "safe enough" because only very few ###identifier###
    are valid.
    
    To improve this, I would explicitly introduce an array of stuff that can be an identifier
    like
    $identifiers['build_date']=date('Y-m-d');
    This would make sure only what is clearly defined as an identifer will get replaced.
    Otherwise, this could cause serious trouble:
    // This is where the ###output### of the script starts
    
    But we don't have to make this perfect now. We can start using it and see how good
    it works and improve it over time.
    

    Reported by crazy4chrissi on 2013-03-21 20:58:40

  44. dreadnaut
    | "if defined" is not what the script does. If I append ###bla### to header.txt,
    | it will get removed in phpliteadmin.php (i.e. replaced by nothing)
    
    Ah, I knew I had forgotten something. Fixed it: if the variable is not defined, the
    string will not be replaced. Also, I added a $build_data array (similar to $identifiers
    as you suggested) which works for both ###something### and #VAR, which I have renamed
    as #EXPORT, though.
    
    I also reshaped the build script comments into some kind of documentation, and added
    a few checks and warning when unexpected stuff happens (missing files, undefined variables).
    
    I fairly happy with this version, so if no-one has further comments on it I'm ready
    to commit it under 1.9.5.
    

    Reported by dreadnaut on 2013-03-22 15:02:54

    <hr> * Attachment: 1.9.5-test-d.zip

  45. Christopher Kramer reporter
    Thanks a lot for your great work!
    
    Looks very good. I think we can start using it, so please commit it in 1.9.5.
    But please have a look at the commits that have been made to the 1.9.5 branch and make
    sure they won't get reverted.
    

    Reported by crazy4chrissi on 2013-03-23 13:05:59

  46. dreadnaut
    Here we go: rebased on the latest 1.9.5 and committed as r385.
    

    Reported by dreadnaut on 2013-03-24 16:35:30 - Status changed: Fixed

  47. dreadnaut
    Of course I made a mix-up while diffing my index.php with the code from 1.9.5. with
    r386 I noticed a first sign, and r387 fixes the last issues —mainly, I forgot to remove
    some of the code split to external files.
    

    Reported by dreadnaut on 2013-03-24 17:23:21

  48. Christopher Kramer reporter
    Thanks a lot!
    
    I just had another idea: With this build-system that works much like conditional compilation
    in C (#IFDEF), we could offer different builds of PLA like one with support for SQLitev2
    and one only for v3. I think there should be a bunch of code in the DB-class (and,
    unfortunately, not only there :( ) that is only a sqlite2 workaround.
    
    But let's forget this, we have a lot more important things to do. Saving 10 KB of size
    for some users probably will never be worth the effort of releasing and maintaining
    multiple versions.
    

    Reported by crazy4chrissi on 2013-03-25 09:24:59

  49. Christopher Kramer reporter
    I noticed a problem:
    
    Currently, custom functions are defined both in phpliteadmin.config.sample.php and
    in (built) phpliteadmin.php.
    
    Thus, renaming phpliteadmin.config.sample.php to phpliteadmin.config.php yields this
    error:
    Fatal error: Cannot redeclare md5rev() ...
    
    I see two solutions:
    1. insert # REMOVE_FROM_BUILD into phpliteadmin.config.sample.php
    + This will make phpliteadmin.php a bit smaller.
    - But users might be confused by the comments (but removing them does not break anything
    as long as they don't build pla).
    2. function_exists() around all custom function declarations.
    + Users understand function_exists()
    -- the function in phpliteadmin.php gets used because it is defined earlier. Users
    will be confused that changing phpliteadmin.config.php does have no effect.
    
    So I guess we need to go for 1.
    

    Reported by crazy4chrissi on 2013-03-25 23:24:05

  50. Christopher Kramer reporter
    ah, 1 more disadvantage of 1.) :-(
    Does not work the same way during development. index.php will first include the sample-config
    and then the user config. Build command has no effect here. This means developers must
    remove custom functions from their user config.
    

    Reported by crazy4chrissi on 2013-03-25 23:27:45

  51. dreadnaut
    I would leave only one sample custom function, maybe a more interesting one (capitalize?
    leet_text?), and then add a single call to function_exist(). We can improve the comment
    if it looks unclear, but it's an advanced feature that php-ignorant users will probably
    ignore anyway.
    
    
    //a list of custom functions that can be applied to columns in the databases
    //make sure to define every function below if it is not a core PHP function
    $custom_functions = array('md5', 'sha1', 'time', 'strtotime', 'leet_text');
    
    //define all the non-core custom functions
    if (!function_exists('leet_text')) {
      function leet_text($value)
      {
        return str_replace(...);
      }
    }
    

    Reported by dreadnaut on 2013-03-26 19:17:04

  52. Christopher Kramer reporter
    Hmm. But still, I think the function_exists() approach has a real problem: It will use
    the function defined in phpliteadmin.php. So if somebody changes the function in phpliteadmin.config.php,
    his changes will have no effect.
    
    I have another idea: We can just out-comment the function. People who are capable of
    writing a php-function will know what to do ;-)
    
    //define all the non-core custom functions
    /* This is an example function. To use it, remove the comments around it. 
    function leet_text($value)
      {
        return str_replace(...);
      }
    */
    
    But one small problem then would remains: Even lots of users might not add custom functions,
    some might use the example functions that are kind of built-in.
    Okay. Looking at them, probably nobody uses them :-D
    

    Reported by crazy4chrissi on 2013-03-26 19:25:55

  53. dreadnaut
    Ah, comments! The simplest solution is actually the best :)
    
    We should also comment the identifier in the array above
    
    //a list of custom functions that can be applied to columns in the databases
    //make sure to define every function below if it is not a core PHP function
    $custom_functions = array(
      'md5', 'sha1', 'time', 'strtotime',
      // add the names of your custom functions here!
      /* 'leet_text', */
    );
    
    // define your custom functions here!
    /*
    function leet_text($value)
    {
      return str_replace(...);
    }
    */
    

    Reported by dreadnaut on 2013-03-27 01:24:42

  54. Log in to comment