Example #1
0
    public function testBugCompileEmptyFunction()
    {
        Artifex::execute(<<<'EOF'
#* function foo()
#* end
EOF
);
        $this->assertTrue(true);
    }
Example #2
0
 /**
  *  @dataProvider fixturesProvider
  */
 public function testFixtures($file, $expected)
 {
     $vm = Artifex::load($file);
     $this->assertEquals($expected, $vm->run());
 }
Example #3
0
 protected function compile()
 {
     $this->readFilters();
     $this->createUrlObjects();
     $groups = $this->groupByMethod($this->urls);
     $groups->iterate(array($this, 'groupByPartsSize'));
     $groups->iterate(array($this, 'groupByPatterns'));
     $groups->sort(function ($obj1, $obj2) {
         return $obj1->getWeight() - $obj2->getWeight();
     });
     $config = $this->config;
     $output = $this->config->getOutput();
     $self = $this;
     $args = compact('self', 'groups', 'config', 'complex');
     $vm = \Artifex::load(__DIR__ . '/Template/Main.tpl.php', $args);
     $vm->doInclude('Switch.tpl.php');
     $vm->doInclude('Url.tpl.php');
     $vm->doInclude('If.tpl.php');
     /**
      *  Convert every Url or UrlGroup object into
      *  code :-)
      */
     $vm->registerFunction('render', function ($obj) use($vm) {
         if ($obj instanceof UrlGroup_Switch) {
             $fnc = 'render_group';
         } else {
             if ($obj instanceof UrlGroup_If) {
                 $fnc = 'render_if';
             } else {
                 if ($obj instanceof Url) {
                     $fnc = 'render_url';
                 } else {
                     if (is_array($obj)) {
                         $fnc = $vm->getFunction('render');
                         $buf = '';
                         foreach ($obj as $url) {
                             $buf .= $fnc($url);
                         }
                         return $buf;
                     } else {
                         throw new \RuntimeException("Don't know how to render " . get_class($obj));
                     }
                 }
             }
         }
         $fnc = $vm->getFunction($fnc);
         return $fnc($obj);
     });
     $vm->registerFunction('callback_object', $callback = function ($annotation) use($vm, $self, $output) {
         if ($annotation->isFunction()) {
             return var_export('\\' . $annotation['function'], true);
         } else {
             if ($annotation->isMethod()) {
                 $class = "\\" . $annotation['class'];
                 $obj = "\$obj_filt_" . substr(sha1($class), 0, 8);
                 return "array({$obj}, " . var_export($annotation['function'], true) . ')';
             } else {
                 throw new \RuntimeException("Invalid callback");
             }
         }
     });
     /**
      *  Generate the callback function (from a function or
      *  a method)
      */
     $vm->registerFunction('callback', $callback = function ($annotation) use($vm, $self, $output) {
         $fileHash = '$file_' . substr(sha1($annotation['file']), 0, 8);
         $filePath = $annotation['file'];
         if (!empty($output)) {
             $filePath = Path::getRelative($annotation['file'], $output);
         }
         // prepare loading of the method/function
         // by doing this we avoid the need of having an "autoloader",
         // also autoloaders doesn't work with functions, this solution does.
         $vm->printIndented("if (empty({$fileHash})) {\n");
         $vm->printIndented("   {$fileHash} = 1;\n");
         if (!empty($output)) {
             $vm->printIndented('   require_once __DIR__ . "/' . addslashes($filePath) . '";' . "\n");
         } else {
             $vm->printIndented('   require_once "' . addslashes($filePath) . '";' . "\n");
         }
         $vm->printIndented("}\n");
         // Get Code representation out of arguments array
         $args = func_get_args();
         array_shift($args);
         $args = array_map(function ($param) {
             $param = is_scalar($param) ? (string) $param : $param;
             $text = !empty($param[0]) && $param[0] == '$' ? $param : var_export($param, true);
             return $text;
         }, $args);
         // check if the filter is cachable
         switch (count($args)) {
             case 3:
                 $cache = intval($annotation->getOne('Cache'));
                 break;
             case 1:
                 $zargs = $annotation->getMetadata();
                 $zargs = $zargs['params'];
                 for ($i = 1; $i < count($zargs); $i++) {
                     $args[] = '$req->get(' . var_export(substr($zargs[$i], 1), true) . ')';
                 }
                 break;
         }
         $arguments = implode(", ", $args);
         if ($annotation->isFunction()) {
             // generate code for functions
             $function = "\\" . $annotation['function'];
             if (!empty($cache)) {
                 return '$this->doCachedFilter(' . var_export($function, true) . ", {$arguments}, {$cache})";
             } else {
                 return "{$function}({$arguments})";
             }
         } else {
             if ($annotation->isMethod()) {
                 // It is a method, *for now* we don't care if the method
                 // is static so we instanciate an object if it wasn't done before
                 $class = "\\" . $annotation['class'];
                 $method = $annotation['function'];
                 $obj = "\$obj_filt_" . substr(sha1($class), 0, 8);
                 $vm->printIndented("if (empty({$obj})) {\n");
                 $vm->printIndented("    {$obj} = new {$class};\n");
                 $vm->printIndented("}\n");
                 if (!empty($cache)) {
                     return '$this->doCachedFilter(array(' . "{$obj}, '{$method}'), {$arguments}, {$cache})";
                 } else {
                     return "{$obj}->{$method}({$arguments})";
                 }
             } else {
                 throw new \RuntimeException("Invalid callback");
             }
         }
     });
     /**
      *  Generate expressions
      */
     $vm->registerFunction('expr', function ($rules) use($self, $callback) {
         if (!is_array($rules)) {
             $rules = array($rules);
         }
         if (count($rules) == 0) {
             return '';
         }
         $expr = array();
         foreach ($rules as $rule) {
             $expr[] = $rule->getExpr($self, $callback) ?: '';
         }
         return implode(' && ', array_filter($expr));
     });
     $this->output = $vm->run();
     //$this->output = FixCode::fix($vm->run());
 }
Example #4
0
<?php

require "lib/Artifex.php";
Artifex::registerAutoloader();
function safe_eval($code)
{
    $namespace = "Artifex\\test\\x" . uniqid(true);
    eval("namespace {$namespace} ;\n " . $code);
    return $namespace;
}
Example #5
0
    public function testDefineScope()
    {
        $vm = Artifex::compile(<<<'EOF'
#* $foo = "foo"
#* $methods = [1, 2]
#* function defineClass($foo, $methods)
class __foo__ {
    #* foreach ($methods as $method) 
    public function set__method__() {
    }
    #* end
}
#* end
EOF
);
        $function = $vm->getFunction("defineClass");
        try {
            /* it fails because the main 
               scope haven't run yet and the variables
               $foo and $methods doens't exists yet */
            $code = $function();
            $this->assertTrue(false);
        } catch (\RuntimeException $e) {
            $this->assertTrue(true);
        }
        $vm->run();
        $code = $function();
        $namespace = safe_eval($code);
        $class = $namespace . '\\foo';
        $this->assertTrue(class_exists($class));
        $this->assertTrue(is_callable($class, 'set1'));
        $this->assertTrue(is_callable($class, 'set2'));
    }
Example #6
0
 public function doInclude($tpl)
 {
     $file = $this->getPath($tpl);
     $vm = \Artifex::load($file, $this->variables);
     $fnc = array_merge($this->functions, $vm->functions);
     $this->functions = $fnc;
     $vm->functions = $fnc;
     return $vm->run();
 }