Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Preprocessing PHP to remove functionality from built files

Tags:

php

build

ant

phing

I've been reading about Phing and Ant and I'm not sure which, if either, of these tools are most useful for this scenario.

It could easily be debug statements etc, but I'll give you our literal scanario.

We have a free and premium version of a downloadable PHP app, and rather than including just a variable hidden somewhere and then doing:

if($premium == true) {
   echo 'some additional functionality';
} else {
    echo 'basic functionality';
}

Obviously someone could then take the source and change that variable, and bang - they've stolen our code. And something like Ioncube etc is just totally unwieldy in my experience and support on hosting companies is just not good enough.

I would prefer something.. perhaps similar to this:

## if premium ##
echo 'some additional functionality';
## else ##
echo 'basic functionality';
## endif ##

And then I would run two builds, one setting the premium to true and one to false, which would generate two files of simply:

echo 'some additional functionality';

and

echo 'basic functionality';

It would also be very helpful to be able to only include entire files based on this same condition passed to the build app.

I can't find a way to do this but I am open to any alternative ideas if possible.

Help would be outstanding,

UPDATE

Using the C preprocessor is great and looks like it does everything I need. However, I can't find how to do the following 3 things.

#1 I need to remove the comments generated into the output files. Below is an example of those.

# 1 "./index.php"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "./index.php"

I haven't found an example of how to do this in the manual page you linked me to.

#2 I need to make it recursively go through every discovered file. When I run my current code I get an error: ../target/./folder/test.php: No such file or directory

So basically I have my 'source' folder which I'm in, which contains a subfolder called 'folder' and it doesn't recreate that, nor the files inside it (test.php)

#3 I'm sure this one is easy - how can I get it to process .js files and probably .html just to be safe as well? In one call, I mean. I assume running it on .jpg etc etc files is a bad idea..

Thanks again!

like image 925
Marc Fowler Avatar asked May 27 '11 14:05

Marc Fowler


2 Answers

Sorry for digging up this topic, but I had the same need and the CPP approach had too many side-effects for my use.

So I developed a basic pre-processor filter for phing that does the trick:

#ifdef premium
  echo 'some additional functionality';
#else
  echo 'basic functionality';
#endif

The filter is available on github: https://github.com/tmuguet/PreProcessorFilter

like image 151
tmuguet Avatar answered Oct 01 '22 21:10

tmuguet


I have come to an idea, the answer before this is accepted but I want to share it anyways. So here is the deal:

Store all the payed features in seperate files. With a hook class, you can check and add the features where you want. Do not include the payed features on free version of the build. You will have 2 zip files but one source.

Here is very simple Hook class that might help you:

Class Hook {
    var $features_enabled;
    public function __construct() {
        // Construction codes goes here.
        // You can check features files. If there is, require them once
        // if there isnt any, define a variable:
        if (file_exists("./features/feature1.php")) {
            require_once './features/feature1.php';

            // set this true. so we can check the features and run it
            $this->features_enabled = TRUE;
        }
        else {
            // there is no feature avaliable. So there is no need to check functions.
            $this->features_enabled = FALSE;
        }
    }

    /**
     * Check the Feature.
     *
     * @param string The feature name
     * @param array|string|... The arguments that you want to pass.
     */
    public function check($feature_name, $args = NULL) {
        // if features cannot be included on constructor, do not need to check.
        if ($this->features_enabled == FALSE)
            return;

        // if feature is a function: check it then run it
        if (function_exists($feature_name))
            $feature_name($args);

        // if feature is a Class: create it then return it.
        if (class_exists($feature_name))
            return new $feature_name($args);
    }
}

Then you can check them in anywhere on your code. Example:

$hook = new Hook();

//.... Codes goes here.

// This will check for a function of class. If there is, execute it
$hook->check('feature_badges');

I know it's very simple and need to develop in many other ways. But If you can manage it:

  • You will seperate the features. This way, you can create different packages.
  • You will check the features with class. Even if user see the feature name, it doesn't matter. Because he cannot see the feature's code.
like image 35
Valour Avatar answered Oct 01 '22 21:10

Valour