Well I read from PHP.net that this can be accomplished with php's shell_exec($command) function:
http://php.net/manual/en/function.shell-exec.php

The idea is that a future version of my script will need a PECL extension called runkit(perfect for making plugins that dynamically add controller action methods), but users of my script may be on webhosts that do not have this extension pre-installed. This can be a problem, I am pretty sure more than 95% of them dont know how to install a PHP extension with PECL or PEAR even if their webhosts provide such an option. For this reason I am attempting to carry this out through my script's installer, which not only install/configure the database tables, but also the necessary PHP extensions required to run the script.

So the question is, is this possible? I am sure with Dedicated host and VPS it should not have any issues, but how about shared hosts and even free hosts? Will the function shell_exec($command) actually work(as the sample code I'm showing below)? Or will it get blocked by the webhosts? Thx.

<?php
$command = "sudo pecl install https://github.com/downloads/zenovich/runkit/runkit-1.0.3.tgz";
shell_exec($command);
?>

    I would guess wager that it wouldn't work on any shared hosts because I highly doubt that they would give the web server permission to sudo. In fact, even most dedicated and vps wouldn't be set up that way, you'd have to have permission to run a sudo command which I doubt any one with sense would have turned on for the web server. Therefore, they'd have to know how to do that, and if they now how to do that, they can probably install the required extensions. 🙂

      I see, that sucks... I mean, some of the users are struggling to set up FTP, and if I force them to have to install a PHP extension they will all be gone. sigh Thanks for your comment though.

        I'm not that much of a fan of after-the-fact rewriting of compiled code; it always feels like an admission that either the application writer or the language itself wasn't up to the task of doing what was needed in the first place.

          Weedpacket;11027215 wrote:

          I'm not that much of a fan of after-the-fact rewriting of compiled code; it always feels like an admission that either the application writer or the language itself wasn't up to the task of doing what was needed in the first place.

          Well the idea here is to allow plugins to dynamically append a new action method to the controller. Without runkit, you will have to edit the controller script file, this can be a problem for software design since once a new version comes out, users either wont be able to upgrade or will have to end up losing their old script modification.

            Why can't users inherit from the controller class?

              Weedpacket;11027219 wrote:

              Why can't users inherit from the controller class?

              Well they technically can, but the script has a router that instantiates corresponding appcontroller objects with a pattern-matching technique. Heres an example, note the frontcontroller part can be empty if the user is browsing the main site, while the value is 'admincp' if admin users access admin control panel:

              www.domain.com/frontcontroller/appcontroller/action/param-1/param-2.../param-n

              So if you create a plugin controller extending an appcontroller, the router will not be able to recognize the child class anyway, you still end up with the parent appcontroller class that does not have the required controller action for plugin.

                So anyone know how to solve this issue? What is your way of creating a plugin that adds a different action to the controller?

                  A dispatch table is the first idea that springs to mind for me:

                  class Controller
                  {
                  	private $plugins = [];
                  
                  
                  public function addPlugin($foo)
                  {
                  	$this->plugins[] = $foo;
                  }
                  public function removePlugin($foo)
                  {
                  	$key = array_search($foo, $this->plugins, true);
                  	if($key !== false)
                  	{
                  		unset($this->plugins[$key]);
                  	}
                  }
                  
                  public function __call($func, $args)
                  {
                  	foreach($this->plugins as $plugin)
                  	{
                  		if(method_exists($plugin, $func))
                  		{
                  			return call_user_func_array([$plugin, $func], $args);
                  		}
                  	}
                  }
                  }
                  
                  class Britches
                  {
                  	public function getFunky()
                  	{
                  		return "FUNKY!";
                  	}
                  }
                  
                  $t = new Controller;
                  $t->addPlugin(new Britches);
                  echo $t->getFunky();
                  

                  Obviously there'd be more to it than that in a real implementation (there are things like having the plugin publish its interface (say as a set of Command objects), conflict resolution, and so on), but it's just there to illustrate the idea in under fifty lines.

                    4 days later
                    Write a Reply...