<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre, #msg p { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[12044] trunk:
  Allow for plugins to enhance the number of metadata fields captured from plugin and theme headers
 .</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.wordpress.org/changeset/12044">12044</a></dd>
<dt>Author</dt> <dd>westi</dd>
<dt>Date</dt> <dd>2009-10-15 21:07:00 +0000 (Thu, 15 Oct 2009)</dd>
</dl>

<h3>Log Message</h3>
<pre>Allow for plugins to enhance the number of metadata fields captured from plugin and theme headers. See <a href="http://trac.wordpress.org/ticket/8964">#8964</a> props strider72.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpadminincludespluginphp">trunk/wp-admin/includes/plugin.php</a></li>
<li><a href="#trunkwpincludesfunctionsphp">trunk/wp-includes/functions.php</a></li>
<li><a href="#trunkwpincludesthemephp">trunk/wp-includes/theme.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpadminincludespluginphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-admin/includes/plugin.php (12043 => 12044)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-admin/includes/plugin.php        2009-10-15 20:45:32 UTC (rev 12043)
+++ trunk/wp-admin/includes/plugin.php        2009-10-15 21:07:00 UTC (rev 12044)
</span><span class="lines">@@ -66,38 +66,22 @@
</span><span class="cx">  * @return array See above for description.
</span><span class="cx">  */
</span><span class="cx"> function get_plugin_data( $plugin_file, $markup = true, $translate = true ) {
</span><del>-        // We don't need to write to the file, so just open for reading.
-        $fp = fopen($plugin_file, 'r');
</del><span class="cx"> 
</span><del>-        // Pull only the first 8kiB of the file in.
-        $plugin_data = fread( $fp, 8192 );
</del><ins>+        $default_headers = array( 
+                'Name' =&gt; 'Plugin Name', 
+                'PluginURI' =&gt; 'Plugin URI', 
+                'Version' =&gt; 'Version', 
+                'Description' =&gt; 'Description', 
+                'Author' =&gt; 'Author', 
+                'AuthorURI' =&gt; 'Author URI', 
+                'TextDomain' =&gt; 'Text Domain', 
+                'DomainPath' =&gt; 'Domain Path' 
+                );
</ins><span class="cx"> 
</span><del>-        // PHP will close file handle, but we are good citizens.
-        fclose($fp);
</del><ins>+        $plugin_data = get_file_data( $plugin_file, $default_headers, 'plugin' );
</ins><span class="cx"> 
</span><del>-        preg_match( '|Plugin Name:(.*)$|mi', $plugin_data, $name );
-        preg_match( '|Plugin URI:(.*)$|mi', $plugin_data, $uri );
-        preg_match( '|Version:(.*)|i', $plugin_data, $version );
-        preg_match( '|Description:(.*)$|mi', $plugin_data, $description );
-        preg_match( '|Author:(.*)$|mi', $plugin_data, $author_name );
-        preg_match( '|Author URI:(.*)$|mi', $plugin_data, $author_uri );
-        preg_match( '|Text Domain:(.*)$|mi', $plugin_data, $text_domain );
-        preg_match( '|Domain Path:(.*)$|mi', $plugin_data, $domain_path );
-
-        foreach ( array( 'name', 'uri', 'version', 'description', 'author_name', 'author_uri', 'text_domain', 'domain_path' ) as $field ) {
-                if ( !empty( ${$field} ) )
-                        ${$field} = _cleanup_header_comment(${$field}[1]);
-                else
-                        ${$field} = '';
-        }
-
-        $plugin_data = array(
-                                'Name' =&gt; $name, 'Title' =&gt; $name, 'PluginURI' =&gt; $uri, 'Description' =&gt; $description,
-                                'Author' =&gt; $author_name, 'AuthorURI' =&gt; $author_uri, 'Version' =&gt; $version,
-                                'TextDomain' =&gt; $text_domain, 'DomainPath' =&gt; $domain_path
-                                );
</del><span class="cx">         if ( $markup || $translate )
</span><del>-                $plugin_data = _get_plugin_data_markup_translate($plugin_file, $plugin_data, $markup, $translate);
</del><ins>+                $plugin_data = _get_plugin_data_markup_translate( $plugin_file, $plugin_data, $markup, $translate );
</ins><span class="cx"> 
</span><span class="cx">         return $plugin_data;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkwpincludesfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/functions.php (12043 => 12044)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/functions.php        2009-10-15 20:45:32 UTC (rev 12043)
+++ trunk/wp-includes/functions.php        2009-10-15 21:07:00 UTC (rev 12044)
</span><span class="lines">@@ -3418,4 +3418,65 @@
</span><span class="cx">                 wp_delete_comment($comment['comment_id']);
</span><span class="cx">         }
</span><span class="cx"> }
</span><del>-?&gt;
</del><ins>+
+/**
+ * Parse the file contents to retrieve its metadata.
+ *
+ * Searches for metadata for a file, such as a plugin or theme.  Each piece of 
+ * metadata must be on its own line. For a field spanning multple lines, it
+ * must not have any newlines or only parts of it will be displayed.
+ *
+ * Some users have issues with opening large files and manipulating the contents
+ * for want is usually the first 1kiB or 2kiB. This function stops pulling in
+ * the file contents when it has all of the required data.
+ *
+ * The first 8kiB of the file will be pulled in and if the file data is not
+ * within that first 8kiB, then the author should correct their plugin file
+ * and move the data headers to the top.
+ *
+ * The file is assumed to have permissions to allow for scripts to read
+ * the file. This is not checked however and the file is only opened for
+ * reading.
+ *
+ * @since 2.9.0
+ *
+ * @param string $file Path to the file
+ * @param bool $markup If the returned data should have HTML markup applied
+ * @param string $context If specified adds filter hook &quot;extra_&lt;$context&gt;_headers&quot; 
+ */
+function get_file_data( $file, $default_headers, $context = '' ) {
+        // We don't need to write to the file, so just open for reading.
+        $fp = fopen( $file, 'r' );
+
+        // Pull only the first 8kiB of the file in.
+        $file_data = fread( $fp, 8192 );
+
+        // PHP will close file handle, but we are good citizens.
+        fclose( $fp );
+
+        if( $context != '' ) {
+                $extra_headers = apply_filters( &quot;extra_$context&quot;.'_headers', array() );
+
+                $extra_headers = array_flip( $extra_headers );
+                foreach( $extra_headers as $key=&gt;$value ) {
+                        $extra_headers[$key] = $key;
+                }
+                $all_headers = array_merge($extra_headers, $default_headers);
+        } else {
+                $all_headers = $default_headers;
+        }
+
+        
+        foreach ( $all_headers as $field =&gt; $regex ) {
+                preg_match( '/' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, ${$field});
+                if ( !empty( ${$field} ) )
+                        ${$field} = _cleanup_header_comment( ${$field}[1] );
+                else
+                        ${$field} = '';
+        }
+
+        $file_data = compact( array_keys( $all_headers ) );
+        
+        return $file_data;
+}
+?&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkwpincludesthemephp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/theme.php (12043 => 12044)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/theme.php        2009-10-15 20:45:32 UTC (rev 12043)
+++ trunk/wp-includes/theme.php        2009-10-15 21:07:00 UTC (rev 12044)
</span><span class="lines">@@ -170,6 +170,18 @@
</span><span class="cx">  * @return array Theme data.
</span><span class="cx">  */
</span><span class="cx"> function get_theme_data( $theme_file ) {
</span><ins>+        $default_headers = array( 
+                'Name' =&gt; 'Theme Name', 
+                'URI' =&gt; 'Theme URI', 
+                'Description' =&gt; 'Description', 
+                'Author' =&gt; 'Author', 
+                'AuthorURI' =&gt; 'Author URI',
+                'Version' =&gt; 'Version', 
+                'Template' =&gt; 'Template', 
+                'Status' =&gt; 'Status', 
+                'Tags' =&gt; 'Tags'
+                );
+
</ins><span class="cx">         $themes_allowed_tags = array(
</span><span class="cx">                 'a' =&gt; array(
</span><span class="cx">                         'href' =&gt; array(),'title' =&gt; array()
</span><span class="lines">@@ -185,59 +197,41 @@
</span><span class="cx">                 'strong' =&gt; array()
</span><span class="cx">         );
</span><span class="cx"> 
</span><del>-        $theme_data = implode( '', file( $theme_file ) );
-        $theme_data = str_replace ( '\r', '\n', $theme_data );
-        if ( preg_match( '|Theme Name:(.*)$|mi', $theme_data, $theme_name ) )
-                $name = $theme = wp_kses( _cleanup_header_comment($theme_name[1]), $themes_allowed_tags );
-        else
-                $name = $theme = '';
</del><ins>+        $theme_data = get_file_data( $theme_file, $default_headers, 'theme' );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Theme URI:(.*)$|mi', $theme_data, $theme_uri ) )
-                $theme_uri = esc_url( _cleanup_header_comment($theme_uri[1]) );
-        else
-                $theme_uri = '';
</del><ins>+        $theme_data['Name'] = $theme_data['Title'] = wp_kses( $theme_data['Name'], $themes_allowed_tags );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Description:(.*)$|mi', $theme_data, $description ) )
-                $description = wptexturize( wp_kses( _cleanup_header_comment($description[1]), $themes_allowed_tags ) );
-        else
-                $description = '';
</del><ins>+        $theme_data['URI'] = esc_url( $theme_data['URI'] );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Author URI:(.*)$|mi', $theme_data, $author_uri ) )
-                $author_uri = esc_url( _cleanup_header_comment($author_uri[1]) );
-        else
-                $author_uri = '';
</del><ins>+        $theme_data['Description'] = wptexturize( wp_kses( $theme_data['Description'], $themes_allowed_tags ) );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Template:(.*)$|mi', $theme_data, $template ) )
-                $template = wp_kses( _cleanup_header_comment($template[1]), $themes_allowed_tags );
-        else
-                $template = '';
</del><ins>+        $theme_data['AuthorURI'] = esc_url( $theme_data['AuthorURI'] );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Version:(.*)|i', $theme_data, $version ) )
-                $version = wp_kses( _cleanup_header_comment($version[1]), $themes_allowed_tags );
-        else
-                $version = '';
</del><ins>+        $theme_data['Template'] = wp_kses( $theme_data['Template'], $themes_allowed_tags );
</ins><span class="cx"> 
</span><del>-        if ( preg_match('|Status:(.*)|i', $theme_data, $status) )
-                $status = wp_kses( _cleanup_header_comment($status[1]), $themes_allowed_tags );
</del><ins>+        $theme_data['Version'] = wp_kses( $theme_data['Version'], $themes_allowed_tags );
+
+        if ( $theme_data['Status'] == '' )
+                $theme_data['Status'] = 'publish';
</ins><span class="cx">         else
</span><del>-                $status = 'publish';
</del><ins>+                $theme_data['Status'] = wp_kses( $theme_data['Status'], $themes_allowed_tags );
</ins><span class="cx"> 
</span><del>-        if ( preg_match('|Tags:(.*)|i', $theme_data, $tags) )
-                $tags = array_map( 'trim', explode( ',', wp_kses( _cleanup_header_comment($tags[1]), array() ) ) );
</del><ins>+        if ( $theme_data['Tags'] == '' )
+                $theme_data['Tags'] = array();
</ins><span class="cx">         else
</span><del>-                $tags = array();
</del><ins>+                $theme_data['Tags'] = array_map( 'trim', explode( ',', wp_kses( $theme_data['Tags'], array() ) ) );
</ins><span class="cx"> 
</span><del>-        if ( preg_match( '|Author:(.*)$|mi', $theme_data, $author_name ) ) {
-                if ( empty( $author_uri ) ) {
-                        $author = wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags );
</del><ins>+        if ( $theme_data['Author'] == '' ) {
+                $theme_data['Author'] = __('Anonymous');
+        } else {
+                if ( empty( $theme_data['AuthorURI'] ) ) {
+                        $theme_data['Author'] = wp_kses( $theme_data['Author'], $themes_allowed_tags );
</ins><span class="cx">                 } else {
</span><del>-                        $author = sprintf( '&lt;a href=&quot;%1$s&quot; title=&quot;%2$s&quot;&gt;%3$s&lt;/a&gt;', $author_uri, __( 'Visit author homepage' ), wp_kses( _cleanup_header_comment($author_name[1]), $themes_allowed_tags ) );
</del><ins>+                        $theme_data['Author'] = sprintf( '&lt;a href=&quot;%1$s&quot; title=&quot;%2$s&quot;&gt;%3$s&lt;/a&gt;', $theme_data['AuthorURI'], __( 'Visit author homepage' ), wp_kses( $theme_data['Author'], $themes_allowed_tags ) );
</ins><span class="cx">                 }
</span><del>-        } else {
-                $author = __('Anonymous');
</del><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return array( 'Name' =&gt; $name, 'Title' =&gt; $theme, 'URI' =&gt; $theme_uri, 'Description' =&gt; $description, 'Author' =&gt; $author, 'Version' =&gt; $version, 'Template' =&gt; $template, 'Status' =&gt; $status, 'Tags' =&gt; $tags );
</del><ins>+        return $theme_data;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span></span></pre>
</div>
</div>

</body>
</html>