[wp-hackers] Theme and Plugin Integration

Owen Winkler ringmaster at midnightcircus.com
Sun Apr 3 19:53:32 GMT 2005

Jeff Minard wrote:

> It was brought up a while ago that each theme folder have a plugins 
> folder inside it, ie:
> default/header.php
> default/plugins/time-since.php
> And that after determining what theme was being used, plugins would be 
> loaded from that theme's plugin folder. I personally like that option 
> best. Great for authors, way easier for users -- also makes "themeing" 
> have many more powerful options.
> (It does raise the issue of plugins being loaded twice...not sure how 
> to best handle that. Perhaps some file reading and preg_matching of 
> "function xyz" or something.)

For a variety of reasons, I'm not going to support any of my plugins 
that are not installed as per my own installation instructions.  And 
end-user will have to contact the theme author for support of plugins 
that I wrote that are somehow installed with a theme.  Should I provide 
an upgrade to a plugin that came with a theme, users can figure out how 
to install it without my help or simply not have the bug-fixes or 
additional functionality.  I just don't have time to debug your themes, too.

What I'm taking away from this discussion is basically a flagrant 
disregard on the part of some theme developers for the efforts of the 
plugin authors whose plugins they employ.  Provide documentation for 
your theme on how to get the latest, hopefully most bug-free version of 
the plugin that your theme requires, and recognize the people whose work 
you're using.  Knowing that a theme could so easily take credit (by 
denying or obscuring the credit that the plugin comes with by default) 
for the hard work of a plugin developer by so surreptitiously including 
and mangling the whole plugin distribution makes me ill.

I realize that this plugin/theme combo thing can still be an issue for 
the end user, and since I'm in that crazy "put up or shut up" group 
where you can't complain without offering a concrete solution, here's my 

I've attached a core patch that will let theme developers add multiple 
"Requires:" header lines to themes.  This will allow WordPress to 
display what plugins are required for that theme and detect whether a 
function from that plugin (thus, the whole plugin) is available.  The 
format of the header line is:

Requires: function_name plugin_url description

Only the description parameter can include spaces.  If this header item 
is present in the theme, then WordPress will display the description 
field for every "Requires" entry in the header with a link to the 
specified plugin page.  It will also display either [not detected] or 
[present] depending on whether the function is_callable.  You can 
specify plugin static class methods using the :: operator in the 
function name, such as "MyClass::MyFunction".

Note that this alteration will not prevent a theme from being activated 
for any reason.

It may be useful to add some CSS styles to the div that I added for 
displaying requirements in the admin.css file, just to make it look 
pretty.  The div is classed as "requirements".  The code is also not 
very fancy, and needs localization for the output strings.

This solution may also alleviate a previously mentioned issue of 
customized themes using new plugins after they're altered.  Just add a 
new requirements line when you alter the theme to remember what your 
theme requires.

Please take a minute to consider what including plugin code with a theme 
denies the plugin authors - the only real incentive for their work, credit.


-------------- next part --------------
Index: wp-includes/functions.php
--- wp-includes/functions.php	(revision 2476)
+++ wp-includes/functions.php	(working copy)
@@ -1384,6 +1384,7 @@
 	preg_match("|Author:(.*)|i", $theme_data, $author_name);
 	preg_match("|Author URI:(.*)|i", $theme_data, $author_uri);
 	preg_match("|Template:(.*)|i", $theme_data, $template);
+	preg_match_all('/Requires:\\s*([^\\s]*)\\s*([^\\s]*)\\s*(.*)/i', $theme_data, $requirements, PREG_SET_ORDER);
 	if ( preg_match("|Version:(.*)|i", $theme_data, $version) )
 		$version = $version[1];
@@ -1404,7 +1405,7 @@
 		$author = '<a href="' . $author_uri[1] . '" title="' . __('Visit author homepage') . '">' . $author_name[1] . '</a>';
-	return array('Name' => $name, 'Title' => $theme, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template[1]);
+	return array('Name' => $name, 'Title' => $theme, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template[1], 'Requirements' => $requirements);
 function get_themes() {
@@ -1460,6 +1461,7 @@
 		$author = $theme_data['Author'];
 		$template = $theme_data['Template'];
 		$stylesheet = dirname($theme_file);
+		$requirements = $theme_data['Requirements'];
 		if (empty($name)) {
 			$name = dirname($theme_file);
@@ -1505,7 +1507,7 @@
 		if (empty($template_dir)) $template_dir = '/';
 		if (empty($stylesheet_dir)) $stylesheet_dir = '/';
-		$themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Stylesheet' => $stylesheet, 'Template Files' => $template_files, 'Stylesheet Files' => $stylesheet_files, 'Template Dir' => $template_dir, 'Stylesheet Dir' => $stylesheet_dir);
+		$themes[$name] = array('Name' => $name, 'Title' => $title, 'Description' => $description, 'Author' => $author, 'Version' => $version, 'Template' => $template, 'Stylesheet' => $stylesheet, 'Template Files' => $template_files, 'Stylesheet Files' => $stylesheet_files, 'Template Dir' => $template_dir, 'Stylesheet Dir' => $stylesheet_dir, 'Requirements' => $requirements);
 	// Resolve theme dependencies.
Index: wp-admin/themes.php
--- wp-admin/themes.php	(revision 2476)
+++ wp-admin/themes.php	(working copy)
@@ -77,6 +77,22 @@
 		$version = $themes[$theme_name]['Version'];
 		$description = $themes[$theme_name]['Description'];
 		$author = $themes[$theme_name]['Author'];
+		$requirements = $themes[$theme_name]['Requirements'];
+		if(count($requirements) > 0) {
+			$description .= '<div class="requirements">This theme may require these plugins:<ul>';
+			foreach($requirements as $req) {
+				$tocall = $req[1];
+				if(strpos($tocall, '::')>0) $tocall = explode('::', $tocall, 2);
+				if(is_callable($tocall)) {
+					$description .= "<li><a href=\"{$req[2]}\">{$req[3]}</a> [present]</li>";
+				}
+				else {
+					$description .= "<li><em><a href=\"{$req[2]}\">{$req[3]}</a> [not detected]</em></li>";
+				}
+			}
+			$description .= '</ul></div>';
+		}
 		if ($template == $current_template && $stylesheet == $current_stylesheet) {
 			$action = '<strong>' . __('Active Theme') . '</strong>';

More information about the wp-hackers mailing list