Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to programmatically install plugins from wordpress theme

Tags:

php

wordpress

My dream is to include a php file in a theme which checks if a set of plugins are installed, and installs the ones which are not. Kind of like a set of dependencies for the theme, but also just a good way to package theme development to include a set of good plugins.

My questions...

  1. Is there something like this in existence?
  2. Is it possible to achieve from a single php file in a theme folder?
  3. Are there any obvious pit-falls or problems with this approach?
  4. How would I go about achieving this?
    • is it possible to enumerate installed plugins from within theme folder?
    • is it possible to download and place plugin files in the plugins folder?
    • is it possible to activate plugins from within theme directory?
like image 671
Billy Moon Avatar asked Apr 27 '12 15:04

Billy Moon


People also ask

How do I install a WordPress plugin automatically?

Go to Plugins > Add New and enter the name or search term to find the WordPress Plugin you wish to add. To view information about the Plugin, installation help, applicable WordPress versions, etc., click Details under the Plugin name. To install the Plugin, click Install under the Plugin name.

How do I bulk install WordPress plugins?

To install the plugins in bulk, select all by clicking on the checkbox next to 'Plugin' option at the top. Once all the plugins are selected, click on the dropdown menu and choose the 'Install' option. Next, you can click on the 'Apply' button. After that, WordPress will install the plugins one by one.

Can you download an installed plugin from WordPress?

WordPress does not allow you to backup or download the plugins before you jettison them from your site. If you also manage your server and are fairly comfortable doing so, you may find a more contrived way to download installed plugins via directory manager app or FTP.


2 Answers

07/06/2018 EDIT: If you are coming across this answer, the code highlighted below is extremely outdated and insecure and should not be used in any capacity outside of experimentation on a local server. If you are looking for a more modern solution for plugin management, consider installing Wordpress via Composer and Bedrock


I would advise NOT programatically checking for the existence of certain plugins, downloading, installing, and activating them from within any theme file. You have to consider that the check will be run every time the given page is loaded, and can result in a lot of superfluous code and unnecessary activity.

Instead, my advice would be to package any plugins on which your theme depends as a part of the theme itself, and NOT as a plugin. Plugins should be installed at the discretion of the user. If a theme depends on a plugin to function properly or efficiently, then it really should be packaged and downloaded with the theme itself.

But to answer your questions directly:

  1. Probably. It is certainly possible to do.
  2. Yes.
  3. See the above. You potentially run into more issues by constantly checking for plugins and running a series of actions based on those conditions rather than just including everything needed.
  4. Plenty of research

    • Probably
    • Yes
    • Yes

I cannot stress enough, however, that the purpose of a PLUGIN is to give the user the option to extend a given theme's capabilities. If your theme's capabilities DEPEND on existing plugins, then you really REALLY should include all the files when somebody downloads your theme.

Though if you feel that your approach benefits your theme in ways that I might be missing, feel free to write it however you like.

COMPLETE ANSWER: I decided to help create a proof of concept for you, because I got bored and curious. Much of this should be self explanatory. Add these functions:

function mm_get_plugins($plugins)
{
    $args = array(
            'path' => ABSPATH.'wp-content/plugins/',
            'preserve_zip' => false
    );

    foreach($plugins as $plugin)
    {
            mm_plugin_download($plugin['path'], $args['path'].$plugin['name'].'.zip');
            mm_plugin_unpack($args, $args['path'].$plugin['name'].'.zip');
            mm_plugin_activate($plugin['install']);
    }
}
function mm_plugin_download($url, $path) 
{
    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $data = curl_exec($ch);
    curl_close($ch);
    if(file_put_contents($path, $data))
            return true;
    else
            return false;
}
function mm_plugin_unpack($args, $target)
{
    if($zip = zip_open($target))
    {
            while($entry = zip_read($zip))
            {
                    $is_file = substr(zip_entry_name($entry), -1) == '/' ? false : true;
                    $file_path = $args['path'].zip_entry_name($entry);
                    if($is_file)
                    {
                            if(zip_entry_open($zip,$entry,"r")) 
                            {
                                    $fstream = zip_entry_read($entry, zip_entry_filesize($entry));
                                    file_put_contents($file_path, $fstream );
                                    chmod($file_path, 0777);
                                    //echo "save: ".$file_path."<br />";
                            }
                            zip_entry_close($entry);
                    }
                    else
                    {
                            if(zip_entry_name($entry))
                            {
                                    mkdir($file_path);
                                    chmod($file_path, 0777);
                                    //echo "create: ".$file_path."<br />";
                            }
                    }
            }
            zip_close($zip);
    }
    if($args['preserve_zip'] === false)
    {
            unlink($target);
    }
}
function mm_plugin_activate($installer)
{
    $current = get_option('active_plugins');
    $plugin = plugin_basename(trim($installer));

    if(!in_array($plugin, $current))
    {
            $current[] = $plugin;
            sort($current);
            do_action('activate_plugin', trim($plugin));
            update_option('active_plugins', $current);
            do_action('activate_'.trim($plugin));
            do_action('activated_plugin', trim($plugin));
            return true;
    }
    else
            return false;
}

... and then execute like so:

$plugins = array(
    array('name' => 'jetpack', 'path' => 'http://downloads.wordpress.org/plugin/jetpack.1.3.zip', 'install' => 'jetpack/jetpack.php'),
    array('name' => 'buddypress', 'path' => 'http://downloads.wordpress.org/plugin/buddypress.1.5.5.zip', 'install' => 'buddypress/bp-loader.php'),
    array('name' => 'tumblr-importer', 'path' => 'http://downloads.wordpress.org/plugin/tumblr-importer.0.5.zip', 'install' => 'tumblr-importer/tumblr-importer.php')
);
mm_get_plugins($plugins);

'name' can be anything, as it serves to be more of a temporary value. 'path' is exactly what it looks like, and is the direct URL to the zip file on the Wordpress server. The 'install' value is simply the path to the main PHP script that has all of the plugin information. You will have to know the layout of that particular plugin directory in order to fill out this information, as this is also required for the activation hack to work.

Activation function was found here (credit to sorich87): https://wordpress.stackexchange.com/questions/4041/how-to-activate-plugins-via-code

WARNING: This is by no means a very safe way to do things. I actually think that this can be abused quite easily, so our best bet is to use this as our baseline and try and improve from there.

If you should decide to use this approach, all I ask is that I'm credited with the initial overall script, along with sorich87 for his activation process may God have mercy on your soul.

07/06/2018 EDIT: Seriously, don't do this. By today's standards, this code is hot garbage. Plugin management should be done through Composer and Bedrock.

like image 175
maiorano84 Avatar answered Nov 15 '22 04:11

maiorano84


Inspired by the comment from Jamie Dixon I inspected how Wordpress works.

The process can be seen in /wp-admin/update.php from line 93. A short version could be made like this:

include_once( ABSPATH . 'wp-admin/includes/plugin-install.php' ); //for plugins_api..

$plugin = 'plugin-name';

$api = plugins_api( 'plugin_information', array(
    'slug' => $plugin,
    'fields' => array(
        'short_description' => false,
        'sections' => false,
        'requires' => false,
        'rating' => false,
        'ratings' => false,
        'downloaded' => false,
        'last_updated' => false,
        'added' => false,
        'tags' => false,
        'compatibility' => false,
        'homepage' => false,
        'donate_link' => false,
    ),
));

//includes necessary for Plugin_Upgrader and Plugin_Installer_Skin
include_once( ABSPATH . 'wp-admin/includes/file.php' );
include_once( ABSPATH . 'wp-admin/includes/misc.php' );
include_once( ABSPATH . 'wp-admin/includes/class-wp-upgrader.php' );

$upgrader = new Plugin_Upgrader( new Plugin_Installer_Skin( compact('title', 'url', 'nonce', 'plugin', 'api') ) );
$upgrader->install($api->download_link);

If you don't want the feedback displayed you should create a custom Skin class. For example:

$upgrader = new \Plugin_Upgrader( new Quiet_Skin() );

class Quiet_Skin extends \WP_Upgrader_Skin {
    public function feedback($string)
    {
        // just keep it quiet
    }
}
like image 45
Tomas Avatar answered Nov 15 '22 05:11

Tomas