<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">
<channel>
<title>DEVTRENCH Post Feed</title>
<link>http://devtrench.com/</link>
<description>Feeding You The Latest Posts From DEVTRENCH</description>
<lastBuildDate>Thu, 17 May 2012 21:08:17 +0000</lastBuildDate>
<language>en-us</language>

<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/devtrench" /><feedburner:info uri="devtrench" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>devtrench</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><item>
<title><![CDATA[WordPress to MODx Migration Part 3: Templates, Categories, and Postmeta]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/0lemLWIn6bQ/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta</link>
<guid isPermaLink="false">http://devtrench.com/posts/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta</guid>
<pubDate>Wed, 25 Aug 2010 21:19:00 +0000</pubDate>
<description>&lt;p&gt;Alright, I'm back for part three of this action packed &lt;strong&gt;WordPress to MODx Migration&lt;/strong&gt; mania.  In &lt;a href="/first-impressions-of-xpdo-wordpress-to-modx-migration-tool/"&gt;part one&lt;/a&gt; I showed you how to use xPDO to connect to the WordPress database and import post content into MODx.  In &lt;a href="/wordpress-to-modx-migration-part-2-schema-relationships-and-comments/"&gt;part two&lt;/a&gt; I demonstrated how xPDO handles table relationships by importing WordPress comments into MODx.  In this part of the WordPress to MODx migration I'm going to show you how to create and assign templates, migrate categories and postmeta data. &lt;/p&gt;
&lt;p&gt;Before we start, I'm glad to say that I've created an account on &lt;a href="https://github.com/devtrench"&gt;GitHub&lt;/a&gt; and have personally switched from SVN to Git.  This came about because of MODx's switch from SVN to Git, and I'm glad that they did, because I've found that I like Git &lt;strong&gt;a lot&lt;/strong&gt; more than SVN.  That said, the code for this script is now hosted on GitHub at &lt;a href="http://github.com/devtrench/WordPress-to-MODx"&gt;http://github.com/devtrench/WordPress-to-MODx&lt;/a&gt;.  Since this code is still for developers only, there's no official release in the downloads section (or on MODx), and I'll most likely keep it that way until it's packaged for the masses.  However, placing it on GitHub does mark the beta release of this code, so please test it out if you're doing a WP to MODx conversion.  Any feedback would be greatly appreciated!  If you just want the script you can get it from GitHub. Below and on the following pages, is the continued explanation of how it works for those who are interested.&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;Templates&lt;/h3&gt;
&lt;p&gt;Templates are the backbone of the Template Variable system in MODx. So in order to migrate Categories and Postmetas from WordPress into MODx as Template Variables, we first need to create the Templates in MODx that they will be assigned to.  In order to do this we must pick id numbers for the templates and assign those in the configuration section of the script.  &lt;/p&gt;
&lt;pre class='brush: php'&gt;
/**
 * template ids to use during import
 * if you would like to have different templates for posts and pages you can
 * specify that below, if not they will default to the default template id
 * if the templates don't exist they will be created.  The default template id
 * must be set.
 */
$default_template_id = 1;
$post_template_id = 2;
$page_template_id = 3;
&lt;/pre&gt;
&lt;p&gt;The template id can be the id of an existing template, or if the template doesn't exist, a new template with that id will be created.  I place the template ids from the configuration into an array and check for their existence in the code below:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
// set up our default templates in an array
if (!empty($default_template_id))
  $templates['default'] = $default_template_id;
if (!empty($post_template_id))
  $templates['post'] = $post_template_id;
if (!empty($page_template_id))
  $templates['page'] = $page_template_id;

// now check that the templates exist
foreach($templates as $template_name =&amp;gt; $template_id)
{
  $template = $template_name . '_template';
  if(!empty($template_id) &amp;amp;&amp;amp; !$$template = $modx-&amp;gt;getObject('modTemplate',$template_id))
  {
    $$template = $modx-&amp;gt;newObject('modTemplate');
    $data = array(
            'id' =&amp;gt; $post_template_id,
            'templatename' =&amp;gt; 'Auto Generated ' . ucwords($template_name) . ' Template',
            'content' =&amp;gt; '',
    );
    $$template-&amp;gt;fromArray($data,'',true);
    $$template-&amp;gt;save();
  }
}
&lt;/pre&gt;
&lt;p&gt;You can see that I check to see if the Template already exists by using xPDO to get the Template object by its id.  If it doesn't exist I create a new modTemplate object, and save it with the id given in the configuration.  You can set primary keys for xPDO objects by passing 'true' as the third parameter in the &lt;a href="http://api.modxcms.com/xpdo/om/xPDOObject.html#fromArray"&gt;fromArray&lt;/a&gt; method.  &lt;/p&gt;
&lt;p&gt;&lt;a href="/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta?page=2"&gt;&lt;em&gt;Continue on to Migrating Related Categories...&lt;/em&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;!--nextpage--&gt;&lt;/p&gt;
&lt;h3&gt;Migrating Related Categories&lt;/h3&gt;
&lt;p&gt;Once the Templates are created we can start to create Template Variables to hold data related to posts.  One important piece of post data is what Category it belongs to. In pre 2.3 versions of WordPress, this information was so important as to give it it's own 'categories' table.  In WordPress 2.3 and above, Categories are now mapped with WordPress's Taxonomy system which introduced the ability to use Tags.  However, the Categories vs Tags debate has been around in WordPress for a while because there is really no difference (especially from a database standpoint).  WordPress posts can have multiple categories as well as multiple tags, so it makes sense to me to just combine these two 'features' and give you the option to call them whatever you want when you migrate to MODx.&lt;/p&gt;
&lt;p&gt;By default, I call them 'Tags' in MODx since I think that fits more with the available tutorials for MODx blogging resources, and I believe that is what they truly are.  I once read in a WordPress forum that Categories are supposed to be like folders (so one category per post), and Tags are, well, tags (ie. go crazy and label your content however you want).   With MODx, we can use containers as Categories and the new Tags template variable for tag based categorization.  This script doesn't set up any category folders since I don't know what to do about cross categorization, so that step will have to be done post migration if it's something that is needed.  For the rest of this post you can consider Categories and Tags to mean the same thing, and they are used interchangeably.&lt;/p&gt;
&lt;p&gt;To migrate Categories and Tags from WordPress you first have to set the $categories_tv variable to the name you want to use for them ("Tags" is the default).&lt;/p&gt;
&lt;pre class='brush: php'&gt;
/**
 * the name of the template variable that you want to use for your categories.
 * If it doesn't exist, it will be created. Leave blank if you don't want to
 * import categories
 */
$categories_tv = 'Tags';
&lt;/pre&gt;
&lt;p&gt;If the $categories_tv variable is set to the name of your choice then a template variable will be created with that name if it doesn't already exist:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
// now add the category TV
if(!empty($categories_tv) &amp;amp;&amp;amp; is_null($category_tv = $modx-&amp;gt;getObject('modTemplateVar',array('name'=&amp;gt;$categories_tv))))
{
  $category_tv = $modx-&amp;gt;newObject('modTemplateVar');
  $data = array(
          'name' =&amp;gt; $categories_tv,
          'caption' =&amp;gt; $categories_tv,
          'type' =&amp;gt; 'text',
  );
  $category_tv-&amp;gt;fromArray($data);
  $category_tv-&amp;gt;save();
  $category_tv_id = $category_tv-&amp;gt;get('id');

  foreach($templates as $template_name =&amp;gt; $template_id)
  {
    if($template_id)
    {
      $tv_link = $modx-&amp;gt;newObject('modTemplateVarTemplate');
      $tv_link-&amp;gt;set('templateid',$template_id);
      $tv_link-&amp;gt;set('tmplvarid',$category_tv_id);
      $tv_link-&amp;gt;set('rank',1);
      $tv_link-&amp;gt;save();
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;First I find the categories template variable by it's name.  If it doesn't exist, then it's created and assigned to each of the Templates that were created previously.  I can see now that I need to move the template assignment outside of the conditional statement that checks for the template since the Template Variable may already exist.  We'll call that bug #1, and &lt;s&gt;I'll fix it in the next push to GitHub&lt;/s&gt; this is already fixed in GitHub.&lt;/p&gt;
&lt;p&gt;Migrating categories while keeping them related to their respective posts is done inside of the post migration loop:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
  /**
   * categories migration ------------------------------------------------------
   *
   * categories use a template variable to store categories.  This is a tag
   * based structure combines wordpress categories and tags into one field
   */
  if(!empty($categories_tv) &amp;amp;&amp;amp; is_object($resource))
  {
    $term_relationsips = array();
    $term_taxonomies = array();
    $terms = array();

    $term_relationsips = $post-&amp;gt;getMany('TermRelationships');
    if (!is_array($term_relationsips)) continue;

    foreach($term_relationsips as $tr)
    {
      $term_taxonomies[] = $tr-&amp;gt;getOne('TermTaxonomys');
    }
    if (!is_array($term_taxonomies)) continue;

    foreach($term_taxonomies as $tt)
    {
      $term = $tt-&amp;gt;getOne('Terms');
      $terms[] = $term-&amp;gt;get('name');
    }

    // if categories exist add it to the templatevar for this resource
    if (count($terms) &amp;gt; 0)
    {
      $terms = join(',',$terms);
      $tv = $modx-&amp;gt;newObject('modTemplateVarResource');
      $tv-&amp;gt;set('tmplvarid',$category_tv_id);
      $tv-&amp;gt;set('contentid',$res_id);
      $tv-&amp;gt;set('value',$terms);
      $tv-&amp;gt;save();
    }
  }
&lt;/pre&gt;
&lt;p&gt;xPDO comes to the rescue again as I use it to first get the category relationships (TermRelationships) for the current post.  Each relationship has a corresponding Taxonomy which in turn has a corresponding Term.  If it sounds confusing, it is.  xPDO handles it well though, and we end up creating a new Template Variable Resource for each tag with a relationship to the category Template Variable and the migrated post.  You'll note that there's no mention of 'categories' or 'tags' in the xPDO queries.  This is because categories and tags exist side by side in the WordPress tables and we can get all of them simply by finding the ones related to the current post.  The only difference between them on the WordPress side is how they are labeled in the Taxonomy table.  This label allows the potential of only migrating categories &lt;em&gt;or&lt;/em&gt; tags, but that's left as an exercise for the user for now.  &lt;/p&gt;
&lt;p&gt;&lt;a href="/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta?page=3"&gt;&lt;em&gt;Continue on to Migrating Postmetas...&lt;/em&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;!--nextpage--&gt;&lt;/p&gt;
&lt;h3&gt;Postmetas&lt;/h3&gt;
&lt;p&gt;Postmetas are the dumping ground for any extra data related to posts. They're like MODx template variables with a few differences: 1) many postmetas hold information that is hidden from the user (MODx Template Variables are displayed by default), 2) Postmetas that are displayed to the user either show up as Custom Fields (which, AFAIK, are only textarea inputs), or are shown in a variety of ways by plugins.  Regardless of these differences, the fact is that data in the WordPress Postmeta table is small bits of information in relationship with their post.  This makes them perfect for Template Variables.&lt;/p&gt;
&lt;p&gt;Postmeta creation is done by finding all of the unique keys in the Postmeta table and creating template variables based on those names:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
// set up all wp postmeta options up as template variables
$criteria = $wp-&amp;gt;newQuery('Postmeta');
$criteria-&amp;gt;groupby('meta_key');
$criteria-&amp;gt;sortby('meta_key','ASC');
$postmetas = $wp-&amp;gt;getCollection('Postmeta',$criteria);

foreach ($postmetas as $meta)
{
  // create each meta tv
  $meta_tv = $modx-&amp;gt;newObject('modTemplateVar');
  $data = array(
          'name' =&amp;gt; $meta-&amp;gt;get('meta_key'),
          'caption' =&amp;gt; $meta-&amp;gt;get('meta_key'),
          'type' =&amp;gt; 'textarea',
  );
  $meta_tv-&amp;gt;fromArray($data);
  $meta_tv-&amp;gt;save();
  $meta_tv_id = $meta_tv-&amp;gt;get('id');
  $meta_tv_ids[$meta-&amp;gt;get('meta_key')] = $meta_tv-&amp;gt;get('id');

  // link the postmeta tvs to the templates
  foreach($templates as $template_name =&amp;gt; $template_id)
  {
    if($template_id)
    {
      $tv_link = $modx-&amp;gt;newObject('modTemplateVarTemplate');
      $tv_link-&amp;gt;set('templateid',$template_id);
      $tv_link-&amp;gt;set('tmplvarid',$meta_tv_id);
      $tv_link-&amp;gt;set('rank',1);
      $tv_link-&amp;gt;save();
    }
  }
}
&lt;/pre&gt;
&lt;p&gt;The first block of code in this snippet gets a collection of postmetas using a custom criteria.  The custom criteria is needed because we need the distinct meta_keys in the table, and this is done with groupby().  Next, I iterate over each distinct postmeta key and create a new Template Variable.  When the new Template Variable is created, it's added to a special array that uses the meta_key for the array key and the new id for the value.  This array is used later to retrieve the id of the Template Variable.  Then, like for Tags, I assign each new Template Variable to the Templates we created. &lt;/p&gt;
&lt;p&gt; Like Tags, Postmetas are migrated in the post migration loop:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
  /**
   * post meta migration -------------------------------------------------------
   */
  $postmetas = '';
  $criteria = $wp-&amp;gt;newQuery('Postmeta');
  $criteria-&amp;gt;where(array(
          'post_id' =&amp;gt; $post-&amp;gt;get('ID'),
  ));
  $postmetas = $wp-&amp;gt;getCollection('Postmeta',$criteria);
  if (is_array($postmetas))
  {
    foreach($postmetas as $meta)
    {
      $tv = $modx-&amp;gt;newObject('modTemplateVarResource');
      $tv-&amp;gt;set('tmplvarid',$meta_tv_ids[$meta-&amp;gt;get('meta_key')]);
      $tv-&amp;gt;set('contentid',$res_id);
      $tv-&amp;gt;set('value',$meta-&amp;gt;get('meta_value'));
      $tv-&amp;gt;save();
    }
  }
&lt;/pre&gt;
&lt;p&gt;First I find if the current post has any Postmetas using an xPDO query.  Since we're not retrieving the collection based on a primary key, we need a custom criteria to set the where clause to find postmetas based on the post ID.  If there are postmetas I create a new Template Variable Resource for each one and set up the relationships to both the Template Variable it belongs to, and the resource.  As you can see this done simply by setting the appropriate id values the tmplvarid and contentid fields.  The value is also stored of course.&lt;/p&gt;
&lt;p&gt;&lt;a href="/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta?page=4"&gt;&lt;em&gt;Continue on to find out what's next for DEVTRENCH...&lt;/em&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;!--nextpage--&gt;&lt;/p&gt;
&lt;h3&gt;Where Do We Go From Here?&lt;/h3&gt;
&lt;p&gt;For all intents and purposes this script should be considered workable but not finished.  There are other things we can migrate of course: authors, options, plugins even, but the script is now to the point where I have all of the data I need to migrate this blog into MODx Revolution.  Since that is my main goal, I'm going to spend my time working on that, and come back to this script once the new DEVTRENCH site is up and running.  The next time I post, this site will be running on MODx Revolution, have a new look, and a new, more dedicated focus on serving the MODx community.  I'm pretty much putting my money where my mouth is as a developer and choosing to support MODx over WordPress, especially since I've chosen it for my blogging platform.  I've made my final decision.&lt;/p&gt;
&lt;p&gt;As for the future of this script, I'm well aware that in it's current state it's pretty much a developer only migration tool.  So I plan to make a version that uses Custom Manager Pages to set the configuration options and run the script in a more user friendly fashion.  This has the big plus of being able to be packaged and therefore installed via the new Package Manager in Revolution.  Don't get me wrong though, I don't ever foresee a complicated blog such as this one being able to be migrated without some kind of intermediate intervention by a developer.  It's simply a fact that there are too many custom plugins to account for on the WordPress side to be able to do a straight migration and have everything working in MODx as it did in WordPress.  Case in point, this blog uses plugins for syntax highlighting, a downloader, seo, related posts, etc, none of which exist on the MODx side.  The syntax highlighter, downloader and others make use of WordPress's shortcode feature, so not only does the feature not work on the MODx side, but the content is littered with shortcodes that MODx has no idea what to do with.  It's very much the same as a migration from MODx Evolution to Revolution but worse, and we haven't even gotten into how to make a working blog with our migrated data.  I'm hoping that once I've finished with my migration I have more insight into how to make the process smoother.&lt;/p&gt;
&lt;p&gt;Until then, wish me luck on moving this beast, and as they say, I'll see you on the flip side.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=0lemLWIn6bQ:oZz0UZg7foo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=0lemLWIn6bQ:oZz0UZg7foo:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=0lemLWIn6bQ:oZz0UZg7foo:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=0lemLWIn6bQ:oZz0UZg7foo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=0lemLWIn6bQ:oZz0UZg7foo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=0lemLWIn6bQ:oZz0UZg7foo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=0lemLWIn6bQ:oZz0UZg7foo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=0lemLWIn6bQ:oZz0UZg7foo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=0lemLWIn6bQ:oZz0UZg7foo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/0lemLWIn6bQ" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/wordpress-to-modx-migration-part-3-templates-categories-and-postmeta</feedburner:origLink></item>
<item>
<title><![CDATA[WordPress to MODx Migration Part 2: Schema Relationships and Comments]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/RsgLUc9gIcY/wordpress-to-modx-migration-part-2-schema-relationships-and-comments</link>
<guid isPermaLink="false">http://devtrench.com/posts/wordpress-to-modx-migration-part-2-schema-relationships-and-comments</guid>
<pubDate>Tue, 06 Jul 2010 12:39:09 +0000</pubDate>
<description>&lt;p&gt;In part 1 of this Wordpress to MODx migration I introduced you to xPDO's schema and model generators and started work on migrating wordpress post and page data into MODx.  In this post I'm going to show you how I built the relationships in the wordpress schema file and how I pulled in all of wordpress's comments and kept the threading in tact.  Plus the script has evolved to handle where to store pages vs posts, what to do with versions, keeping child/parent relationships intact, and some basic cleaning up by placing config values in the configuration section.&lt;/p&gt;
&lt;h4&gt;Schema Relationships&lt;/h4&gt;
&lt;p&gt;Previously the schema file that xPDO generated was simply a dump of what it found in the database.  Relationships have to be built manually and I've since done that (as well as getting rid of any tables we don't need, like plugin tables).  I basically followed the wiki on how to make relationships in a schema file and built the relationships based on the table structure and my knowledge of how wordpress works on the database level.  Here is the current schema file which is most likely still a work in progress.&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;pre class='brush: xml'&gt;
&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;model package=&amp;quot;wordpress&amp;quot; baseClass=&amp;quot;xPDOObject&amp;quot; platform=&amp;quot;mysql&amp;quot; defaultEngine=&amp;quot;MyISAM&amp;quot;&amp;gt;

  &amp;lt;object class=&amp;quot;Comments&amp;quot; table=&amp;quot;comments&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;comment_ID&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_post_ID&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_author&amp;quot; dbtype=&amp;quot;tinytext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_author_email&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;100&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_author_url&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;200&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_author_IP&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;100&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_date&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_date_gmt&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_content&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_karma&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;11&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_approved&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;1&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_agent&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;255&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_type&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_parent&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_subscribe&amp;quot; dbtype=&amp;quot;enum&amp;quot; precision=&amp;quot;'Y','N'&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;N&amp;quot; /&amp;gt;
    &amp;lt;aggregate alias=&amp;quot;Users&amp;quot; class=&amp;quot;Users&amp;quot; local=&amp;quot;user_id&amp;quot; foreign=&amp;quot;ID&amp;quot; cardinality=&amp;quot;one&amp;quot; owner=&amp;quot;foreign&amp;quot; /&amp;gt;
  &amp;lt;/object&amp;gt;

	&amp;lt;object class=&amp;quot;Options&amp;quot; table=&amp;quot;options&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;option_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;blog_id&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;11&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;option_name&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;64&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;unique&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;option_value&amp;quot; dbtype=&amp;quot;longtext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;autoload&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;yes&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;Postmeta&amp;quot; table=&amp;quot;postmeta&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;meta_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;meta_key&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;255&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;true&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;meta_value&amp;quot; dbtype=&amp;quot;longtext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;true&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;Posts&amp;quot; table=&amp;quot;posts&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;ID&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_author&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_date&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_date_gmt&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_content&amp;quot; dbtype=&amp;quot;longtext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_title&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_category&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;4&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_excerpt&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_status&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;publish&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_status&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;open&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;ping_status&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;open&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_password&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_name&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;200&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;to_ping&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;pinged&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_modified&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_modified_gmt&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_content_filtered&amp;quot; dbtype=&amp;quot;text&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_parent&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;guid&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;255&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;menu_order&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;11&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_type&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;post&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;post_mime_type&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;100&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;comment_count&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
    &amp;lt;aggregate alias=&amp;quot;Users&amp;quot; class=&amp;quot;Users&amp;quot; local=&amp;quot;post_author&amp;quot; foreign=&amp;quot;ID&amp;quot; cardinality=&amp;quot;one&amp;quot; owner=&amp;quot;foreign&amp;quot; /&amp;gt;
    &amp;lt;composite alias=&amp;quot;Comments&amp;quot; class=&amp;quot;Comments&amp;quot; local=&amp;quot;ID&amp;quot; foreign=&amp;quot;comment_post_ID&amp;quot; cardinality=&amp;quot;many&amp;quot; owner=&amp;quot;local&amp;quot; /&amp;gt;
    &amp;lt;composite alias=&amp;quot;PostMeta&amp;quot; class=&amp;quot;Postmeta&amp;quot; local=&amp;quot;ID&amp;quot; foreign=&amp;quot;post_id&amp;quot; cardinality=&amp;quot;many&amp;quot; owner=&amp;quot;local&amp;quot; /&amp;gt;
    &amp;lt;composite alias=&amp;quot;TermRelationship&amp;quot; class=&amp;quot;TermRelationships&amp;quot; local=&amp;quot;ID&amp;quot; foreign=&amp;quot;object_id&amp;quot; cardinality=&amp;quot;many&amp;quot; owner=&amp;quot;local&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;TermRelationships&amp;quot; table=&amp;quot;term_relationships&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;object_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;pk&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;term_taxonomy_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;pk&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;term_order&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;11&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
	  &amp;lt;aggregate alias=&amp;quot;TermTaxonomy&amp;quot; class=&amp;quot;TermTaxonomy&amp;quot; local=&amp;quot;term_taxonomy_id&amp;quot; foreign=&amp;quot;term_taxonomy_id&amp;quot; cardinality=&amp;quot;one&amp;quot; owner=&amp;quot;foreign&amp;quot; /&amp;gt;
	  &amp;lt;aggregate alias=&amp;quot;Post&amp;quot; class=&amp;quot;Posts&amp;quot; local=&amp;quot;object_id&amp;quot; foreign=&amp;quot;ID&amp;quot; cardinality=&amp;quot;one&amp;quot; owner=&amp;quot;foreign&amp;quot; /&amp;gt;
  &amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;TermTaxonomy&amp;quot; table=&amp;quot;term_taxonomy&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;term_taxonomy_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;term_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;taxonomy&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;32&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;description&amp;quot; dbtype=&amp;quot;longtext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;parent&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;count&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
    &amp;lt;composite alias=&amp;quot;TermRelationship&amp;quot; class=&amp;quot;TermRelationships&amp;quot; local=&amp;quot;term_taxonomy_id&amp;quot; foreign=&amp;quot;term_taxonomy_id&amp;quot; cardinality=&amp;quot;many&amp;quot; owner=&amp;quot;local&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;Terms&amp;quot; table=&amp;quot;terms&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;term_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;name&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;200&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;slug&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;200&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;unique&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;term_group&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;10&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
    &amp;lt;aggregate alias=&amp;quot;TermTaxonomy&amp;quot; class=&amp;quot;TermTaxonomy&amp;quot; local=&amp;quot;term_id&amp;quot; foreign=&amp;quot;term_id&amp;quot; cardinality=&amp;quot;one&amp;quot; owner=&amp;quot;foreign&amp;quot; /&amp;gt;
  &amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;Usermeta&amp;quot; table=&amp;quot;usermeta&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;umeta_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_id&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;meta_key&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;255&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;true&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;meta_value&amp;quot; dbtype=&amp;quot;longtext&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;true&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;

  &amp;lt;object class=&amp;quot;Users&amp;quot; table=&amp;quot;users&amp;quot; extends=&amp;quot;xPDOObject&amp;quot;&amp;gt;
		&amp;lt;field key=&amp;quot;ID&amp;quot; dbtype=&amp;quot;bigint&amp;quot; precision=&amp;quot;20&amp;quot; attributes=&amp;quot;unsigned&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; index=&amp;quot;pk&amp;quot;  generated=&amp;quot;native&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_login&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;60&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;unique&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_pass&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;64&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_nicename&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;50&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; index=&amp;quot;index&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_email&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;100&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_url&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;100&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_registered&amp;quot; dbtype=&amp;quot;datetime&amp;quot; phptype=&amp;quot;datetime&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0000-00-00 00:00:00&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_activation_key&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;60&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;user_status&amp;quot; dbtype=&amp;quot;int&amp;quot; precision=&amp;quot;11&amp;quot; phptype=&amp;quot;integer&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;0&amp;quot; /&amp;gt;
		&amp;lt;field key=&amp;quot;display_name&amp;quot; dbtype=&amp;quot;varchar&amp;quot; precision=&amp;quot;250&amp;quot; phptype=&amp;quot;string&amp;quot; null=&amp;quot;false&amp;quot; default=&amp;quot;&amp;quot; /&amp;gt;
    &amp;lt;composite alias=&amp;quot;Usermeta&amp;quot; class=&amp;quot;Usermeta&amp;quot; local=&amp;quot;ID&amp;quot; foreign=&amp;quot;user_id&amp;quot; cardinality=&amp;quot;many&amp;quot; owner=&amp;quot;local&amp;quot; /&amp;gt;
	&amp;lt;/object&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Once that was done, I deleted all of my generated model files, and regenerated them using the same script from the first post.  Now we have model files with the relationships that we need for posts and comments, and maybe categories (those are next on the list to do).  The nice part about doing the schema relationships and model generation is that once you get it right you're done and can simply copy these files in the future.  That is, if you need to do another Wordpress to MODx migration, you don't have to repeat these steps.&lt;/p&gt;
&lt;h4&gt;New Migration Code&lt;/h4&gt;
&lt;p&gt;Below is the new migration code fully commented for your reading.  This is still very much a work in progress and is here mostly to document my progress.  However, I can see the benefit of adding this code to github for the masses to download once it gets a little more polished.  It also has the potential to become a MODx package (if I figure out how to make one :) ).  The code now includes a GPL license.&lt;/p&gt;
&lt;p&gt;Key areas that have changed since the first iteration are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New configuration section. See lines 47-100&lt;/li&gt;
&lt;li&gt;Some code that truncates the content and comment tables.  The flag used here will be set to false by default in the future, but for now it set to true for my convenience.  See lines 137-145&lt;/li&gt;
&lt;li&gt;Refactored the code that inserts posts and pages.  See lines 170-214&lt;/li&gt;
&lt;li&gt;Added code for inserting comments using quip.  See lines 216-245&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class='brush: php'&gt;
&amp;lt;?php

ini_set('max_execution_time',120);

/**
 * xPDO Wordpress to MODx Migration Code
 * Author James Ehly (devtrench.com)
 *
 * This script uses xpdo to connect to modx and wordpress packages to migrate
 * data from a wordpress database to a modx database
 *
 * The code below may or may not work for your particular wordpress and MODx install.
 * It should be used as a reference point, and you should customize it to your
 * specific needs, but I hope that most general cases are covered.
 *
 * This script is intended to be run on a new install of MODx Revolution.  If
 * you are using an existing MODx Revo install then the script will probably
 * work but might have some unexpected results. So, backup your data first, and
 * use at your own risk.
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * @author James Ehly &amp;lt;james@devtrench.com&amp;gt;
 * @copyright Copyright 2010, James Ehly
 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License v2
 * @todo - figure out categories and other template variables
 * @todo - figure out post authors
 *
 */

################################################################################
# Configuration
################################################################################

/**
 * a flag to turn this script on and off
 */
$can_migrate = true;

/**
 * Wordpress Database settings
 *
 * $wp_database_host     string database hostname
 * $wp_database_charset  string database character set
 * $wp_database_name     string database name
 * $wp_database_prefix   string database table prefix
 * $wp_database_username string database username
 * $wp_database_password string database password
 */
$wp_database_host     = 'localhost';
$wp_database_charset  = 'utf-8';
$wp_database_name     = 'wordpress_devtrench';
$wp_database_prefix   = 'wp_';
$wp_database_username = 'root';
$wp_database_password = '';

/**
 * $post_document_parent
 * the MODx document parent id, or array of values (if the page needs to be
 * created) for WP posts. If set to 0 the parent will be the document root.
 * If the id does not exist, a document will be created.
 *
 * integer or array (see modResource for possible values)
 * example array: array('pagetitle'=&amp;gt;'Blog','context_key'=&amp;gt;'web')
 * !! don't forget the context_key or your pages won't show up in your context
 */
$post_document_parent = array(
        'pagetitle'=&amp;gt;'Blog',
        'alias'=&amp;gt;'blog',
        'published'=&amp;gt;1,
        'context_key'=&amp;gt;'web');

/**
 * $page_document_parent
 * the modx document parent id, or array of values (if the page needs to be
 * created) for WP pages. If set to 0, the parent will be the document root.
 * If the id does not exist, a document will be created.
 *
 * integer or array (see modResource for possible values)
 * example array: array('pagetitle'=&amp;gt;'Blog')
 */
$page_document_parent = 0;

/**
 * $empty_tables
 * if set to true, the tables that will be updated are emptied first.
 */
$empty_tables = true;

################################################################################

if (!$can_migrate) die('Migration cannot be processed, this script is off.');

// Include the xpdo and modx classes
include ('../../xpdo/xpdo.class.php');
include ('../../model/modx/modx.class.php');

// Instantiate a new modx object.  MODx inherits from xpdo so we can use it
// like an xpdo object, but it has the extra functions needed for saving content.
// Thanks to Shaun McCormick for writing docs on this.
$modx = new modX();
$modx-&amp;gt;initialize('web');

// Add the Quip package
$can_migrate_comments = $modx-&amp;gt;addPackage( 'quip', '../../components/quip/model/',
        $modx-&amp;gt;db-&amp;gt;config['table_prefix'] );

// Now instantiate a new xpdo object and add our wordpress package.  This gives
// us the ability to make queries on the wordpress database as an xpdo object.
$wp = new xPDO('mysql:host=' . $wp_database_host .
                ';dbname=' . $wp_database_name .
                ';charset=' . $wp_database_charset,
        $wp_database_username,
        $wp_database_password );

$can_migrate_wp = $wp-&amp;gt;addPackage('wordpress','../',$wp_database_prefix);

if (!$can_migrate_wp) die('Wordpress Package could not be loaded.');

/**
 * during migrations where you need to try, try and try again to get it right,
 * it's easier to truncate the tables here instead of doing it manually.
 * setting $empty_tables to true will delete data from the following tables.
 */
if($empty_tables)
{
  if ($can_migrate_comments)
  {
    $modx-&amp;gt;db-&amp;gt;query('TRUNCATE ' . $modx-&amp;gt;getFullTableName('quip_comments'));
    $modx-&amp;gt;db-&amp;gt;query('TRUNCATE ' . $modx-&amp;gt;getFullTableName('quip_comments_closure'));
  }
  $modx-&amp;gt;db-&amp;gt;query('TRUNCATE ' . $modx-&amp;gt;getFullTableName('site_content'));
}

// first we set up our document parents
$post_parent = setupParent($post_document_parent, 'Post');
if ($post_parent === false)
  die('There was an error setting up the post parent.
       Check your configuration value for $post_document_parent');

$page_parent = setupParent($page_document_parent, 'Page');
if (!$page_parent === false)
  die('There was an error setting up the page parent.
       Check your configuration value for $page_document_parent');

// get all wordpress posts.  Isn't this so easy?
$posts = $wp-&amp;gt;getCollection('Posts');

$post_count = 0;
$comment_count = 0;

// iterate over each post and create a new modResource object, mapping our post
// fields to our wordpress fields
foreach($posts as $post)
{
  $resource = '';

  // logic for adding posts
  $type = $post-&amp;gt;get('post_type');

  switch($type)
  {
    case 'post':
      $parent = $post_parent;
      $document_type = 'document';
      break;
    case 'page':
      $parent = $post-&amp;gt;get('post_parent');
      $parent = (!empty($parent)) ? $parent : $page_parent;
      $document_type = 'document';
      break;
    case 'attachment':
      $document_type = 'attachment';
      break;
    case 'revision':
      $document_type = 'revision';
      break;
    default:

  }

  if ($document_type == 'document')
  {
    $resource = $modx-&amp;gt;newObject('modResource');
    $data = array(
            'id'=&amp;gt;$post-&amp;gt;get('ID'),
            'content'=&amp;gt;$post-&amp;gt;get('post_content'),
            'pagetitle'=&amp;gt;$post-&amp;gt;get('post_title'),
            'context_key'=&amp;gt;'web',
            'alias'=&amp;gt;$post-&amp;gt;get('post_name'),
            'published'=&amp;gt; ($post-&amp;gt;get('post_status') == 'publish') ? 1 : 0,
            'pub_date'=&amp;gt; ($post-&amp;gt;get('post_status') == 'publish') ? $post-&amp;gt;get('post_date') : 0,
            'parent' =&amp;gt; $parent,
            'template'=&amp;gt; 1,
    );
    $resource-&amp;gt;fromArray($data,'',true);

    // call the save function which inserts our object record into the database.
    $resource-&amp;gt;save();
    $post_count++;
    $res_id = $resource-&amp;gt;get('id');
  }

  if ($can_migrate_comments)
  {
    // get wp comments that are related to this post
    // Thanks BobRay for showing me how to do this
    $criteria = $wp-&amp;gt;newQuery('Comments');
    $criteria-&amp;gt;where(array(
            'comment_post_ID' =&amp;gt; $post-&amp;gt;get('ID'),
    ));
    $criteria-&amp;gt;sortby('comment_ID','ASC');

    $comments = $post-&amp;gt;getMany('Comments',$criteria);
    if (!is_null($comments))
    {
      foreach($comments as $comment)
      {
        $quip = $modx-&amp;gt;newObject('quipComment');
        $comment_data = array(
                'id'=&amp;gt;$comment-&amp;gt;get('comment_ID'),
                'thread'=&amp;gt;$post-&amp;gt;get('post_title') . '_' . $post-&amp;gt;get('ID'),
                'parent'=&amp;gt;$comment-&amp;gt;get('comment_parent'),
                'author'=&amp;gt;$comment-&amp;gt;get('user_id'),
                'body'=&amp;gt;$comment-&amp;gt;get('comment_content'),
                'name'=&amp;gt;$comment-&amp;gt;get('comment_author'),
                'email'=&amp;gt;$comment-&amp;gt;get('comment_author_email'),
                'website'=&amp;gt;$comment-&amp;gt;get('comment_author_url'),
                'ip'=&amp;gt;$comment-&amp;gt;get('comment_author_ip'),
                'createdon'=&amp;gt;$comment-&amp;gt;get('comment_date'),
                'resource'=&amp;gt;$res_id, // here's where the comment is joined to the post
        );
        $quip-&amp;gt;fromArray($comment_data,'',true);
        $quip-&amp;gt;save();
        $comment_count++;
      }
    }
  }
}

// Processing is now finished. Echo the number of posts inserted.
echo $post_count . ' post' . (($post_count == 1) ? '' : 's') . ' added. ' . $comment_count . ' comment' . (($comment_count == 1) ? '' : 's') . ' added.';
echo 'If you are done with migrating posts you should remove this file or set $can_migrate to false so this page can\'t be executed in the future.';

/**
 * creates a parent resource for posts and pages
 *
 * input integer | array (parent values), string (container name)
 * returns integer or false
 */
function setupParent($parent, $type='Undefined')
{
  global $wp,$modx;

  // if the parent is 0 return true
  if ($parent === 0)
  {
    return $parent;
  }

  // if the parent is an integer, get the resource
  if (is_integer($parent))
  {
    $parent_resource = $modx-&amp;gt;getObject('modResource',$parent);
  }

  // if the parent already exists return true
  if(is_object($parent_resource))
  {
    return $parent;
  }

  // if the parent is null (resource not found), or the parent is an array,
  // create the resource
  if (is_null($parent_resource) || is_array($parent))
  {
    if (is_integer($parent))
      $parent = array('id'=&amp;gt;$parent,'pagetitle'=&amp;gt;$type . ' Container','published'=&amp;gt;1);

    $resource = $modx-&amp;gt;newObject('modResource');
    $resource-&amp;gt;fromArray($parent,'',true);
    $resource-&amp;gt;save();
    return $resource-&amp;gt;get('id');
  }
  else
  {
    // don't know what happened so fail
    return false;
  }
}

?&amp;gt;
&lt;/pre&gt;
&lt;p&gt;That's all I have time to write on this for now. The past few weeks have been incredibly busy for me, so I'm glad that I was able to get this far and push out the code where it is.  Part 3 will include mapping wordpress categories and authors, and hopefully the first commit into GitHub.&lt;/p&gt;
&lt;p&gt;Once the script is finished I'm gonna migrate this blog, kiss Wordpress goodbye and say hello to MODx (and probably a ton of comment spam). Comment spam aside, I'm really looking forward to being able to work on this site in MODx.  Maybe I can work in Akismet integration next if someone hasn't already done that.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=RsgLUc9gIcY:4JrmU9r6pXo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=RsgLUc9gIcY:4JrmU9r6pXo:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=RsgLUc9gIcY:4JrmU9r6pXo:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=RsgLUc9gIcY:4JrmU9r6pXo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=RsgLUc9gIcY:4JrmU9r6pXo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=RsgLUc9gIcY:4JrmU9r6pXo:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=RsgLUc9gIcY:4JrmU9r6pXo:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=RsgLUc9gIcY:4JrmU9r6pXo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=RsgLUc9gIcY:4JrmU9r6pXo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/RsgLUc9gIcY" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/wordpress-to-modx-migration-part-2-schema-relationships-and-comments</feedburner:origLink></item>
<item>
<title><![CDATA[WordPress to MODx Migration Part 1: First Impressions of xPDO]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/1zwkwSOR8cw/first-impressions-of-xpdo-wordpress-to-modx-migration-tool</link>
<guid isPermaLink="false">http://devtrench.com/posts/first-impressions-of-xpdo-wordpress-to-modx-migration-tool</guid>
<pubDate>Thu, 20 May 2010 17:04:20 +0000</pubDate>
<description>&lt;p&gt;I wrote in my &lt;a href="/modxpo-2010"&gt;last post&lt;/a&gt; that I want to move this blog from WordPress to MODx and so I thought this would be a good real world lesson in using &lt;a href="http://www.xpdo.org"&gt;xPDO&lt;/a&gt;.  Rather than custom coding a database migration tool using plain old php like I've done in the past, I thought it would be cool to see what xPDO could do, how easy it would be, and how robust xPDO is.  I've spent 2 hours on the code below and have never used xPDO before, and so far I'm pretty impressed with what xPDO can do. It's nice to work with a lightweight ORM tool that just does it's thing without extra framework code to wade through.  I've used the &lt;a href="http://www.doctrine-project.org/"&gt;Doctrine ORM&lt;/a&gt; in &lt;a href="http://www.symfony-project.org/"&gt;Symfony&lt;/a&gt; for quite a while and its a bit complex a bloated (do we really need DQL?), so compared to that, I found xPDO faster and easier to learn.&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;First, I want to explain my goals for moving this blog to MODx Revolution.  I've used MODx for the past three years and it's time for me to pony up and go all the way with MODx.  I've written a lot on this blog that MODx is great, but it isn't great blog software and that's why I use WordPress.  However, after seeing what Revolution can do, I really believe it changes the game and could actually catch up to WordPress sooner than we think.  Also, using WordPress doesn't help MODx become a better blogging tool, and that's what I'd really like to do.&lt;/p&gt;
&lt;p&gt;I've also had some trouble getting WordPress to do what I want it to do on this site. This site is more than just a blog - it has a tools section with custom PHP code and a tutorials section.  I feel I've had to hack WordPress to get these things done.  The entire time I was coding the templates and custom plugin code to do this, it was always in the back of my mind how easy this would be to do in MODx.  So I've been stuck between having lots of great blog functionality with WordPress, and wanting all the the customization that is so easy with MODx.  I think I can have both with Revolution.&lt;/p&gt;
&lt;p&gt;Below is the beginning of this move, and I'm sharing code at this early state to get feedback from the MODx community and just to share my experience with anyone who is interested.  I'm interested to find out if what I'm doing is a good way to go about it, so if you have suggestions, feel free to comment. The goals of the migration are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It needs to work with my test data the same way that it will work with the real data when I'm ready to make the switch.  This will make it possible for me to keep blogging and approving comments, and migrate the data from the latest DB snapshot when I'm ready to go live.&lt;/li&gt;
&lt;li&gt;It needs to keep relationships in tact.  Comments and metadata need to be related to posts, users to posts, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Setting Up My Local Dev Environment&lt;/h4&gt;
&lt;p&gt;I'm assuming that you have a local LAMP, XAMPP, or MAMP stack set up and running.  WAMP most likely will not work and gave me headaches for a long time with Revolution.  Just use XAMPP on Windows and you'll be fine I think it's a better, more up-to-date product anyway.&lt;/p&gt;
&lt;p&gt;Besides the dev environment, you need two things to get started: 1) an export of your wordpress data using phpMyAdmin's export feature, or one from mysqldump, 2) a running installation of MODx Revolution (I'm currently using MODx Revolution 2.0.0-rc-1 rev6614).&lt;/p&gt;
&lt;p&gt;First you'll need to create a database for your wordpress data.  Mine is called 'wordpress_devtrench' and you'll see it referenced in the code below.  Once you have a database created, simply import your wordpress database into it. You don't need to install WordPress since we just need the data.&lt;/p&gt;
&lt;p&gt;Next, install a &lt;a href="http://www.modxcms.com/download"&gt;fresh copy of Revolution&lt;/a&gt;.  The database I set up is called 'modx_devtrench', and you'll see that referenced below as well.  All database logins are on my local machine so using 'root' with no password fine, just don't do that on your live server.&lt;/p&gt;
&lt;h4&gt;Creating the WordPress Model&lt;/h4&gt;
&lt;p&gt;After getting MODx set up and my WP database installed, the first thing I did was to create a schema and model based on my existing WP database.  Thanks to Jason Coward, this was very easy:&lt;/p&gt;
&lt;pre class='brush: php'&gt;
&amp;lt;?php
/*
 * xPDO Wordpress to MODx Migration Code
 * Author James Ehly (devtrench.com)
 *
 * This code is part of the WP to MODx migration and should go in your
 * core/model/schema directory.  Simply run it from a web browser or cli and
 * it will create the wordpress schema from the database and all of the
 * xpdo objects in core/model/wordpress
 *
 * Once this is done we can run the wp2modx.php script that does the actual
 * data migration.
 *
 * @todo some manual intervention is needed to set up the table relationships we need
 *
 * Thanks to Jason Coward for posting how do set up a schema from a database:
 * http://modxcms.com/forums/index.php/topic,16562.0.html
 */

$mtime= microtime();
$mtime= explode(&amp;quot; &amp;quot;, $mtime);
$mtime= $mtime[1] + $mtime[0];
$tstart= $mtime;

//Customize this line based on the location of your script
include_once (dirname(dirname(dirname(__FILE__))) . '/xpdo/xpdo.class.php');

// set your database credentials to use your wordpress database, and set the wordpress prefix (default is 'wp_')
$xpdo= new xPDO('mysql:host=localhost;dbname=wordpress_devtrench','root','','wp_');

// Set the package name and root path of that package
$xpdo-&amp;gt;setPackage('modx', XPDO_CORE_PATH . '../model/');

$xpdo-&amp;gt;setDebug(true);

$manager= $xpdo-&amp;gt;getManager();
$generator= $manager-&amp;gt;getGenerator();

//Use this to create a schema from an existing database - this will write the wordpress.mysql.schema.xml file
$xml= $generator-&amp;gt;writeSchema(XPDO_CORE_PATH . '../model/schema/wordpress.mysql.schema.xml', 'wordpress', 'xPDOObject', 'wp_');

//Use this to generate classes and maps from your schema
// NOTE: by default, only maps are overwritten; delete class files if you want to regenerate classes
// this will generate all of the model code in core/model/wordpress/
$generator-&amp;gt;parseSchema(XPDO_CORE_PATH . '../model/schema/wordpress.mysql.schema.xml', XPDO_CORE_PATH . '../model/');

$mtime= microtime();
$mtime= explode(&amp;quot; &amp;quot;, $mtime);
$mtime= $mtime[1] + $mtime[0];
$tend= $mtime;
$totalTime= ($tend - $tstart);
$totalTime= sprintf(&amp;quot;%2.4f s&amp;quot;, $totalTime);

echo &amp;quot;\nExecution time: {$totalTime}\n&amp;quot;;
&lt;/pre&gt;
&lt;p&gt;Basically this code creates a schema file (an xml file that describes the database structure), and a folder called 'wordpress' in core/model/.  Inside of the wordpress folder will be all of the model class files that we need to migrate our data using xpdo.&lt;/p&gt;
&lt;h4&gt;Starting The Migration Script&lt;/h4&gt;
&lt;p&gt;Now that we have  an xpdo model to work with that we can start to create the code that will migrate WP data into MODx.  Since the databases are separate, we need 2 xPDO objects: the MODx object and an xPDO object with the WordPress package loaded.&lt;/p&gt;
&lt;p&gt;Once we have the objects created it's simply a matter of getting all the posts and making a loop where we do the mapping between objects.  xPDO makes this so easy with it's getters and setters.  The code is commented pretty well so just go line by line and read it.&lt;/p&gt;
&lt;pre class='brush: php'&gt;
&amp;lt;?php
/*
 * xPDO Wordpress to MODx Migration Code
 * Author James Ehly (devtrench.com)
 *
 * This script uses xpdo to connect to modx and wordpress packages to migrate
 * data from a wordpress database to a modx database
 *
 * The code below may or may not work for your particular wordpress and MODx install.
 * It should be used as a reference point, and you should customize it to your
 * specific needs, but I hope that most general cases are covered.
 *
 * This script is intended to be run on a new install of MODx Revolution.  If
 * you are using an existing MODx Revo install then the script will probably
 * work but might have some unexpected results. So, backup your data first, and
 * use at your own risk.
 *
 */

// Include the xpdo and modx classes
include ('core/xpdo/xpdo.class.php');
include ('core/model/modx/modx.class.php');

// Instantiate a new modx object.  MODx inherits from xpdo so we can use it
// like an xpdo object, but it has the extra functions needed for saving content.
// Thanks to Shaun McCormick for writing docs on this.
$modx = new modX();
$modx-&amp;gt;initialize('web');

// Now instantiate a new xpdo object and add our wordpress package.  This gives
// us the ability to make queries on the wordpress database as an xpdo object.
$wp = new xPDO('mysql:host=localhost;dbname=wordpress_devtrench;charset=utf-8', 'root', '');
$wp-&amp;gt;addPackage('wordpress','core/model/','wp_');

// get all wordpress posts.  Isn't this so easy?
$posts = $wp-&amp;gt;getCollection('Posts');

// iterate over each post and create a new modResource object, mapping our post
// fields to our wordpress fields
foreach($posts as $post)
{
  $resource = '';
  $resource = $modx-&amp;gt;newObject('modResource',array(
    'content'=&amp;gt;$post-&amp;gt;get('post_content'),
    'pagetitle'=&amp;gt;$post-&amp;gt;get('post_title'),
    'context_key'=&amp;gt;'web',
    'alias'=&amp;gt;$post-&amp;gt;get('post_name'),
    'published'=&amp;gt; ($post-&amp;gt;get('post_status') == 'publish') ? 1 : 0,
    'pub_date'=&amp;gt; ($post-&amp;gt;get('post_status') == 'publish') ? $post-&amp;gt;get('post_date') : 0,
    )
  );
  // call the save function which inserts our object record into the database.
  $resource-&amp;gt;save();
}
// we're done
echo 'done.';
?&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This code is pretty simple so far but it works.  After running this script, all of my WordPress posts, pages, and versions are set up as document resources in MODx and I can see and edit them in the manager.  Not bad for 2 hours of research/learning and coding.  The next step will be to create the relationships in my WordPress schema (this has to be done by hand).  Once that is done I'll be able to start to map items related to posts to Template Variables related to my documents.  I also plan to set up Quip to handle comments on the MODx side and figure out how to migrate all of my WP comments.  The appropriate logic will also need to written to handle how WP posts, pages and versions should be migrated to MODx.  For instance, I want my blog posts to be under a main blog page, not under the site root, and I want pages to be directly under the site root (pretty much reverse of what it is now).  Versions will probably just be dropped.&lt;/p&gt;
&lt;p&gt;First impressions are always important, and xPDO has really impressed me so far.  It's turning out to be exactly what I've wanted in MODx for so long; a simple way to get MODx to interact with custom data.  I'm excited to see where this project takes me with MODx Revolution and xPDO.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=1zwkwSOR8cw:QGwYmvVJn3c:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=1zwkwSOR8cw:QGwYmvVJn3c:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=1zwkwSOR8cw:QGwYmvVJn3c:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=1zwkwSOR8cw:QGwYmvVJn3c:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=1zwkwSOR8cw:QGwYmvVJn3c:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=1zwkwSOR8cw:QGwYmvVJn3c:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=1zwkwSOR8cw:QGwYmvVJn3c:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=1zwkwSOR8cw:QGwYmvVJn3c:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=1zwkwSOR8cw:QGwYmvVJn3c:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/1zwkwSOR8cw" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/first-impressions-of-xpdo-wordpress-to-modx-migration-tool</feedburner:origLink></item>
<item>
<title><![CDATA[MODxpo 2010]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/Ys5O3SJciJQ/modxpo-2010</link>
<guid isPermaLink="false">http://devtrench.com/posts/modxpo-2010</guid>
<pubDate>Thu, 13 May 2010 20:44:52 +0000</pubDate>
<description>&lt;p&gt;&lt;a href="http://www.devtrench.com/wp-content/uploads/2010/05/me-and-ryan-thrash-and-jason-coward.jpg"&gt;&lt;img class="alignright size-full wp-image-667" style="border: 1px solid black; margin-left: 10px; float: right;" title="me-and-ryan-thrash-and-jason-coward" src="assets/images/blog/me-and-ryan-thrash-and-jason-coward.jpg" alt="" width="200" height="134" /&gt;&lt;/a&gt;I feel fortunate to have spent the last two days in Dallas, TX with the greatest minds in the MODx world. &lt;a href="http://modxpo.modxcms.com"&gt; MODxpo 2010&lt;/a&gt; was so far above what I expected that I'm at a loss to capture everything that went on.  The most awesome and  most humbling aspect of the conference was the openness, honesty, and down-to-earthness of all of people that attended, including the core team. As &lt;a href="http://modxcms.com/forums/index.php/topic,16101.0.html"&gt;I've written before&lt;/a&gt;, the MODx community is a big reason why I've stuck with it for the past 3 years, but these last two days solidified that for me on a very real level.  I've simply never been around a big group of guys (and one gal), who are doing the same work as me and who know MODx so well.&lt;!--more--&gt;&lt;/p&gt;
&lt;h4 style="margin-bottom: 0;"&gt;The Revolution Is Here&lt;/h4&gt;
&lt;p&gt;I haven't been a big proponent of MODx Revolution, but this weekend convinced me that it's going to be huge.  The work that the MODx core team, especially Jason Coward and Shawn McCormick, have put into Revolution is simply astounding.  During the conference I had the opportunity to talk with both Jason and Shawn at length about my needs for Evo and Revo and it's very apparent that Revolution can handle my needs with native code, while to do what I want to do in Evo I'd have to hack the core and basically fork the project.&lt;/p&gt;
&lt;p&gt;With Revo, I finally can say that MODx is a Content Management Framework (CMF).  I want to be very specific about what I  mean since framework can mean so many things to different people.  By CMF I mean that MODx Revolution lays the foundation on which to build your own Content Management System.  While MODx provides a default manager interface to manage your content, it's possible and quite easy to make a new theme (essentially a copy of the current management) and customize it to your heart's content.  The entire management interface is coded with controllers and views using the smarty templating system, so if you know smarty, it's quite easy to dive  in and start making major changes to the interface - customizing it for your own clients.  This is the direction that I want to take it, but posibilities are endless.  Here are some things that I can envision:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;iPhone/Smart Phone specific management interfaces&lt;/li&gt;
&lt;li&gt;Simplified, No Javascript management interfaces&lt;/li&gt;
&lt;li&gt;Replicas of the Evo manager (w/o frames) to ease transition into Revo&lt;/li&gt;
&lt;li&gt;Blogging and eCommerce specific management interfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The other great thing about the way themes are done in Revo is that you can specify themes at the user level, just as you could in Evo, but instead of just getting some css changes, the entire interface can change.  This makes it possible for power users to have  an advanced interface and client users to something that is lot less intimidating.  It would also be great if you could specify settings at the group level, but I can't tell if that is possible (if you know, please comment).  It's also still possible to modify the management interface with Template Variables, Custom Manager Pages (previously Modules), and plugins just like you could in Evo.&lt;/p&gt;
&lt;p&gt;It seems to me that most developers at the conference had tried Revolution a little bit, maybe just as far as the install.   Few had actually built and were running sites with it, and I think this pretty common because of the stage that Revolution is in. Many developers, myself included, just don't feel comfortable with using a release candidate product on a customer's site.  There are also very real issues of extras not being available, client documentation having to be changed, and getting clients to  pay for what they might see as an unnecessary upgrade.  However, I plan to switch my ehlydesign.com site over to Revolution as soon as possible so that I can start to learn it and become comfortable with it.  I've also had grand thoughts of converting this blog into a Revo site and documenting a Wordpress to MODx conversion.&lt;/p&gt;
&lt;p&gt;So in planning how I will make the switch to Revolution, my plan is to keep all of my current client sites in Evo and keep them all upgraded to the latest version.  I believe that this will make them ready for the day when proper migration tools are built.  Along side this, new sites will be start to be built with Revolution.  I know that some of my sites may never be upgraded to Revolution because they are too customized, have too many users editing content, etc, but that's ok too because Evolution isn't going anywhere and will continue to be supported for quite some time.  If 'core team' support for it would ever end, I feel that there is plenty of community driven support to fill that gap.  I expect the timeline for migration would be somewhere around a year and at the end I'll be supporting a handful of Evo sites that won't be upgraded and everything else will be in Revolution.&lt;/p&gt;
&lt;h4 style="margin-bottom: 0;"&gt;Evolution Is Still Here&lt;/h4&gt;
&lt;p&gt;I don't have a lot to say about MODx Evolution except that it's a still a  great CMS and if you're not using it you should give it a try. I've been  using MODx for the past three years and I don't have any plans to  switch to another CMS ever (even though I think &lt;a href="/modx-sucks"&gt;MODx sucks&lt;/a&gt;).  At the conference, presentations covered  advanced Template Variable usage in Evolution (using the managermanager  plugin), how to streamline your installation and usage of MODx, eCommerce and MODx, MODx security, and general tips and tricks others use in their development.  I think the best session on Evolution was the one where Dell showed how they are using MODx.  I personally learned a lot about faceted classification systems and how to build them with MODx.  They've really pushed Evo to do a lot of different things and it was great to see that.  If you want to see the presentations for yourself, you can &lt;a href="http://www.amdbuilder.net/articles/modxpo"&gt;view them here&lt;/a&gt; thanks to Patrick (AMDBuilder)&lt;/p&gt;
&lt;h4 style="margin-bottom: 0;"&gt;Final Words&lt;/h4&gt;
&lt;p&gt;I really want to take some time in this post to just say thanks to everyone that came to MODxpo 2010 and to the core team.  So if you were at MODxpo these next few words are for you... It was great to meet everyone and figure out the people and personalities behind some of the interesting names we've got in the MODx forums.  It was simply awesome to be around people who share my level of enthusiasm, insight and skill with MODx and to glean so much information from the presentations I saw and conversations we had.  I appreciate the MODx community now more than ever because everyone is so friendly and accepting, no matter what level you come to MODx at.  I think that was really evident at the conference.  It was great to meet &lt;a href="http://www.fireproofsocks.com"&gt;Everett&lt;/a&gt;, Terry (from Apple), &lt;a href="http://www.pleth.com"&gt;Greg&lt;/a&gt;, &lt;a href="http://www.my619.com"&gt;Kris&lt;/a&gt;, &lt;a href="http://www.prowebscape.com/"&gt;Charlie&lt;/a&gt;, &lt;a href="http://www.butter.com.hk"&gt;Glen and James&lt;/a&gt;, &lt;a href="http://www.foxycart.com"&gt;Brett&lt;/a&gt;, &lt;a href="http://www.topspotims.com"&gt;Matt and Jeremy&lt;/a&gt;, &lt;a href="http://www.power10solutions.com"&gt;Mark&lt;/a&gt;, &lt;a href="http://www.amdbuilder.net"&gt;Patrick&lt;/a&gt;, and &lt;a href="http://www.joshholmes.com"&gt;Josh&lt;/a&gt; (and everyone else who said hi).&lt;/p&gt;
&lt;p&gt;I especially want to thank the core team - Ryan Thrash, Jason Coward, Shaun McCormick, Jeff Whitfield and those that couldn't make it.  Thanks for putting so much of your time and money into a product that I basically make a living on.  The project would not be where it is today without your direction, commitment and time spent in the development trenches.  Extra thanks goes to Ryan and his wife Liz, who not only let us into their home for a fun evening of but cooked an awesome Texas sized meal for us all as well.  I'm soooo looking forward to the next MODxpo!&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Ys5O3SJciJQ:D5t2OwRnVHY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Ys5O3SJciJQ:D5t2OwRnVHY:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Ys5O3SJciJQ:D5t2OwRnVHY:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Ys5O3SJciJQ:D5t2OwRnVHY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Ys5O3SJciJQ:D5t2OwRnVHY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Ys5O3SJciJQ:D5t2OwRnVHY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Ys5O3SJciJQ:D5t2OwRnVHY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Ys5O3SJciJQ:D5t2OwRnVHY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Ys5O3SJciJQ:D5t2OwRnVHY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/Ys5O3SJciJQ" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/modxpo-2010</feedburner:origLink></item>
<item>
<title><![CDATA[Troubleshooting Tip: Reduce and Simplify]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/Q7pXUSotT6E/troubleshooting-tip-reduce-and-simplify</link>
<guid isPermaLink="false">http://devtrench.com/posts/troubleshooting-tip-reduce-and-simplify</guid>
<pubDate>Sat, 17 Apr 2010 14:31:33 +0000</pubDate>
<description>&lt;p&gt;If you've coded yourself into a problem that you can't figure out and you've spent hours debugging always remember this simple rule to solve your problems faster:  &lt;em&gt;Reduce and Simplify&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;If a solution to a problem isn't obvious by looking at your code (or output), then start taking chunks away until you don't see the problem anymore.  For example, I was having a tough time figuring out why some web pages I built were very slow in IE 6 &amp;amp; 7, but loaded fine in Firefox.  I had a thumbnail generator that wasn't working right, which I thought was part of the issue, but once that was fixed, the problem still existed.  At that point I should have started reducing the code to find the problem, but instead I kept at my original assumption that something was wrong with the thumbnail generator and spent hours in forums searching for answers.  After a night of rest I came back at the problem and started reducing the code.  The first thing I did was take all the javascript out of the page, and wha-la the slowness disappeared.  Now I knew the problem was with javascript (or so I thought). I found which particular js file was the culprit.  Then upon further inspection found the javascript used a css file and that had some bad paths to images in it:&lt;/p&gt;
&lt;pre class='brush: css'&gt;
/* bad path in IE specific CSS made IE 6 and 7 slow */

.cboxIE #cboxTopLeft{background:transparent; filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src=/js/colorbox_assets/images/internet_explorer/borderTopLeft.png, sizingMethod='scale');}&lt;/pre&gt;
&lt;p&gt;And that was the problem.  Had I remembered how to troubleshoot properly, I could have written this blog post yesterday.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Q7pXUSotT6E:l8SyEgezS4I:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Q7pXUSotT6E:l8SyEgezS4I:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Q7pXUSotT6E:l8SyEgezS4I:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Q7pXUSotT6E:l8SyEgezS4I:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Q7pXUSotT6E:l8SyEgezS4I:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Q7pXUSotT6E:l8SyEgezS4I:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Q7pXUSotT6E:l8SyEgezS4I:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Q7pXUSotT6E:l8SyEgezS4I:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Q7pXUSotT6E:l8SyEgezS4I:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/Q7pXUSotT6E" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/troubleshooting-tip-reduce-and-simplify</feedburner:origLink></item>
<item>
<title><![CDATA[Taking A Different Approach]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/lkS49871kr0/taking-a-different-approach</link>
<guid isPermaLink="false">http://devtrench.com/posts/taking-a-different-approach</guid>
<pubDate>Fri, 16 Apr 2010 08:54:28 +0000</pubDate>
<description>&lt;p&gt;Have you ever asked yourself why you do the things you do?  Why do you design the way you do? Why do code the way you do?  I've been asking this question off and on over my career, but lately this question has really come back to me in a big way.&lt;/p&gt;
&lt;p&gt;I've been reading &lt;a href="http://gettingreal.37signals.com/"&gt;Getting Real&lt;/a&gt; by 37signals and although this is my second reading of it, it's really hit home this time.  The entire book is basically about your approach.  How do you get up every morning and step up to the plate?  For a long time, my basic approach has been, how can I code this as fast as possible so that I can get on to my next project and keep at my ever growing list of tasks.  Ultimately, this very unsatisfying because the quality of work is low, and low quality leads to a ton of other problems.&lt;/p&gt;
&lt;p&gt;So if you're stuck in a rut like this how do you get out and take a different approach?  How do you slow down while keeping up with high demands.  That's my problem: I can't see past the pile of work to know.  So while I would love to "Get Real" now, I'm not to sure that I can all at once.  I do think it all starts with changing my approach and taking a lot of the advice in the book to heart.  It's not going to happen over night, but I've already started to try some of the things they advocate in my symfony development and for the first time it doesn't feel like I'm fighting with symfony.  So for a little while on the blog here I'm going to be wrestling with a few of these questions and tell you about some of the small successes I've had in becoming more real.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=lkS49871kr0:hE5BSj9jyFM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=lkS49871kr0:hE5BSj9jyFM:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=lkS49871kr0:hE5BSj9jyFM:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=lkS49871kr0:hE5BSj9jyFM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=lkS49871kr0:hE5BSj9jyFM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=lkS49871kr0:hE5BSj9jyFM:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=lkS49871kr0:hE5BSj9jyFM:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=lkS49871kr0:hE5BSj9jyFM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=lkS49871kr0:hE5BSj9jyFM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/lkS49871kr0" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/taking-a-different-approach</feedburner:origLink></item>
<item>
<title><![CDATA[Two New Tutorials for MODx and PHP]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/APEFjF-5Rxs/two-new-tutorials-for-modx-and-php</link>
<guid isPermaLink="false">http://devtrench.com/posts/two-new-tutorials-for-modx-and-php</guid>
<pubDate>Wed, 03 Mar 2010 09:00:48 +0000</pubDate>
<description>&lt;p&gt;I've been busy writing and have launched two new tutorials:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devtrench.com/tutorials/modx/modx-templating-strategy/"&gt;&lt;strong&gt;MODx Templating Strategy&lt;/strong&gt;&lt;/a&gt; is tutorial that will show you a best practice for developing scalable templates in MODx CMS.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.devtrench.com/tutorials/php/tools-of-the-trade-for-php/"&gt;&lt;strong&gt;PHP Tools of the Trade&lt;/strong&gt;&lt;/a&gt; is for PHP beginners and will let you in on all of the software and server knowledge that you need if you want to learn PHP.&lt;/p&gt;
&lt;p&gt;These are the first two tutorials that I'm launching on this site after the redesign and I've got more on the way.  Enjoy.&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=APEFjF-5Rxs:GBvB0wlcJ-Q:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=APEFjF-5Rxs:GBvB0wlcJ-Q:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=APEFjF-5Rxs:GBvB0wlcJ-Q:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=APEFjF-5Rxs:GBvB0wlcJ-Q:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=APEFjF-5Rxs:GBvB0wlcJ-Q:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=APEFjF-5Rxs:GBvB0wlcJ-Q:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=APEFjF-5Rxs:GBvB0wlcJ-Q:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=APEFjF-5Rxs:GBvB0wlcJ-Q:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=APEFjF-5Rxs:GBvB0wlcJ-Q:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/APEFjF-5Rxs" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/two-new-tutorials-for-modx-and-php</feedburner:origLink></item>
<item>
<title><![CDATA[DEVTRENCH Blank Theme for Wordpress]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/enCikkIcGU8/blank-theme-for-wordpress</link>
<guid isPermaLink="false">http://devtrench.com/posts/blank-theme-for-wordpress</guid>
<pubDate>Fri, 05 Feb 2010 21:57:43 +0000</pubDate>
<description>&lt;p&gt;Sometimes when starting out a new Wordpress theme it's nice to have something to start from that's pretty bare, but has enough code so that you don't feel like you're reinventing the wheel.  I know there's lots of blank themes out there, but I created my own and this is what I usually start from.  It's basically the default theme, stripped down with reset and typography CSS from blueprint.  This theme has very little - almost none - html markup, but includes the common php tags wordpress uses to display content.  This makes it ideal to start from because you just have to surround the php tags with your XHTML code.&lt;/p&gt;
&lt;p&gt;[download id="13" format="1"]&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;If you use this theme here are a few steps to get your started and is basically the process I go through.  Before creating the Wordpress theme I'm assuming you have XHTML/CSS sources to work from.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Copy your existing CSS into style.css&lt;/li&gt;
&lt;li&gt;Copy your images into the images folder.  To make everything work right, I recommend using the same file structure as a wordpress theme with your CSS and image folder in the same directory.&lt;/li&gt;
&lt;li&gt;Copy the html head and banner protion of your design into the header.php file.  The banner portion of your design is anything that is the same across all parts of your site.  Typically this is logo, menu, search bar, etc.&lt;/li&gt;
&lt;li&gt;Copy the footer portion of your design into footer.html.  Like the banner, the footer is anything at the bottom of your design that is the same across all pages.&lt;/li&gt;
&lt;li&gt;Next, start the homepage design.  You can use the index.php file or copy index.php to a home.php file.  Copy the necessary code from your design template into the wordpress template, surrounding the php tags with your code where necessary.&lt;/li&gt;
&lt;li&gt;Then do the inside or single page template by modifying the single.php page.  Similar to the homepage you'll take your inside page template code and surround the php code in single.php with it.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=enCikkIcGU8:kmPf7zuckcY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=enCikkIcGU8:kmPf7zuckcY:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=enCikkIcGU8:kmPf7zuckcY:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=enCikkIcGU8:kmPf7zuckcY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=enCikkIcGU8:kmPf7zuckcY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=enCikkIcGU8:kmPf7zuckcY:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=enCikkIcGU8:kmPf7zuckcY:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=enCikkIcGU8:kmPf7zuckcY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=enCikkIcGU8:kmPf7zuckcY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/enCikkIcGU8" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/blank-theme-for-wordpress</feedburner:origLink></item>
<item>
<title><![CDATA[Book Review: MODx Web Development from Packt Publishing]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/OJMaS01Bq1g/book-review-modx-web-development-from-packt-publishing</link>
<guid isPermaLink="false">http://devtrench.com/posts/book-review-modx-web-development-from-packt-publishing</guid>
<pubDate>Thu, 31 Dec 2009 11:40:51 +0000</pubDate>
<description>&lt;p&gt;&lt;a href="http://www.devtrench.com/go/modx-web-development/" class='ext' target='_blank'&gt;&lt;img src="assets/images/blog/modx-web-development-packt.png" alt="MODx Web Development" title="modx-web-development-packt" width="100" height="123" class="size-full wp-image-475" style='float:right;margin:0 0 0 10px;border:3px double #666' /&gt;&lt;/a&gt;I want to be honest with you, I've kind of been putting off writing my review of &lt;a href="http://www.devtrench.com/go/modx-web-development/" class='ext' target='_blank'&gt;MODx Web Development&lt;/a&gt; from Packt Publishing.  I actually finished the book about a week ago and just felt like I had to give it some distance so I didn't totally bash this book.  It's not really fair to the author to just outright say that this book isn't good because they put some thought into it and worked hard.  But if I would have written this post a week ago, that's all you would have heard.&lt;/p&gt;
&lt;p&gt;Here is the quick list of pros and cons and further on is my impression of the book.&lt;/p&gt;
&lt;h3&gt;Cons&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The book starts out as a reference guide and ends up as a 'how to make a blog' tutorial.&lt;/li&gt;
&lt;li&gt;It doesn't go very in depth on more advanced topics.  Here is a list of things it doesn't cover at all or very well:
&lt;ul&gt;
&lt;li&gt;Templating Strategies&lt;/li&gt;
&lt;li&gt;Snippet, Plugin, and Module Coding Strategies&lt;/li&gt;
&lt;li&gt;Using the MODx apis&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;It NEVER mentions the full set of document variables, or system variables that are available.  Not even in an appendix (of which there are none).&lt;/li&gt;
&lt;li&gt;Advanced users of MODx are going to be let down by this book.  I didn't learn anything new about MODx from it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons Overall:&lt;/strong&gt; &lt;em&gt;I felt that the book was edited poorly, didn't include enough advanced information, and was incomplete.&lt;/em&gt; &lt;/p&gt;
&lt;h3&gt;Pros&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;It covers a wide variety of topics. The author touches on almost every aspect of MODx including the most common snippets and plugins.&lt;/li&gt;
&lt;li&gt;The book gives links to community resources such as the forum and wiki.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Pros Overall:&lt;/strong&gt; &lt;em&gt;I think if you are new to MODx, then the book would help you to learn it.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;h3&gt;My Review&lt;/h3&gt;
&lt;p&gt;Ok, so now I really get to steamroll over this thing.  The overall statements above, pretty much sum up my feeling about the book.  I think it was poorly edited, isn't for advanced users, and was sadly incomplete, but if you don't know very much about MODx then you could pick up quite a bit from the book.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Poor Editing&lt;/strong&gt;&lt;br /&gt;
While reading the book it felt like the author outlined the sections by topic beforehand, started each chapter with the intention of writing about that topic and then got tired of it and went into whatever suited him.  This was most apparent in the chapter on Templating where the author starts out with how to make and modify templates, then glosses over document and template variables, and then uses the rest of the chapter to do a mini "How to make a blog" tutorial.  The rest of the book follows this haphazard organization. &lt;/p&gt;
&lt;p&gt;The author also has the annoying tendency to write "but I'll talk about [x] in more detail in chapter [x]".  Most of the time I would skip ahead to read the more details, and found that the more details needed more details.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Not For The Advanced&lt;/strong&gt;&lt;br /&gt;
Like I said, I didn't learn anything new from this book and I've been using MODx for about 2-and-a-half years.  I really wanted to see some different strategies for templating, some advanced ways to write snippets, how to use some of the plugin hooks that I've never used, and interesting way's to use modules, but that's all left as an exercise for the reader.  I was really excited when the author said he was going to explain the Meta Keywords and Meta Description system that MODx has built in, because I've never understood why people would use it.  But when I anxiously skipped ahead to chapter 12 where the author said he'd explain it, I was disappointed as I read his half-assed 2 paragraphs that explained how most developers don't use the system.  &lt;em&gt;"[The meta tags and keywords system] is rarely used, since the process for specifying keywords for individual documents is rather cumbersome"&lt;/em&gt;.  Oh, and the picture that was supposed to show the Keywords and Description system was wrong.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It's Not All There&lt;/strong&gt;&lt;br /&gt;
I was shocked when I couldn't find a complete list of document variables or system variables in the entire book.  To me this is a big defect in a book that is supposed to cover the basics.  It doesn't get any more basic than what the system can provide to developers.  I expected that the book would come with an appendix that covered all of these boring but very important variables and the MODx api functions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;It's For The Newbies&lt;/strong&gt;&lt;br /&gt;
I really hate it when authors make the claim that their book is for beginners to advanced users.  This author does, "Both beginners and experienced web developers will benefit from this comprehensive guide to MODx". And it definitely falls short on the advanced side.  If I ever wrote a book about MODx, I would write that the book is for people at my skill level and if you know less you're going to have to pony up and learn some stuff, and if you know more than me, then you can write the next one...or bash it in a blog post.  &lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=OJMaS01Bq1g:Gqp0D_oer80:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=OJMaS01Bq1g:Gqp0D_oer80:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=OJMaS01Bq1g:Gqp0D_oer80:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=OJMaS01Bq1g:Gqp0D_oer80:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=OJMaS01Bq1g:Gqp0D_oer80:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=OJMaS01Bq1g:Gqp0D_oer80:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=OJMaS01Bq1g:Gqp0D_oer80:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=OJMaS01Bq1g:Gqp0D_oer80:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=OJMaS01Bq1g:Gqp0D_oer80:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/OJMaS01Bq1g" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/book-review-modx-web-development-from-packt-publishing</feedburner:origLink></item>
<item>
<title><![CDATA[iPhone vs Blackberry Curve Web Browsing]]></title>
<link>http://feedproxy.google.com/~r/devtrench/~3/Tv_CFfc1yDk/iphone-vs-blackberry-curve-web-browsing</link>
<guid isPermaLink="false">http://devtrench.com/posts/iphone-vs-blackberry-curve-web-browsing</guid>
<pubDate>Tue, 22 Dec 2009 10:09:32 +0000</pubDate>
<description>&lt;p&gt;In September I wrote a post, "&lt;a href="http://www.devtrench.com/duplicate-content-solution-for-mobile-sites/"&gt;Duplicate Content Solution For Mobile Sites&lt;/a&gt;", which was about how to make a mobile version of your website and not get the duplicate content penalty.  In that post I wrote "I've never had the chance of using an iPhone but I can't imagine that a few extra inches of screen space make that big of a difference".  Well, last night my sister came to town for Christmas and I got to mess around with her iPhone for a bit. And the difference is huge.&lt;/p&gt;
&lt;p&gt;It's not just the screen size that makes browsing better, it's the whole touch screen interface.  I was simply amazed at how well the iPhone worked for browsing, and how well the sites I've developed look in it.  Now, in my mind, there's simply no comparison between the experience I have browsing websites on my Curve (which now feels very clunky) and the iPhone.   &lt;/p&gt;
&lt;p&gt;&lt;!--more--&gt;&lt;/p&gt;
&lt;p&gt;I have to admit that I didn't like the touch screen keyboard because it felt alkward and I kept hitting the wrong buttons, but I suppose you get used to it.  What I really want is a full touch screen and a keyboard.  In five years when my wife and I get new phones, I hope that's the norm. &lt;/p&gt;
&lt;p&gt;I'm not sure what this means for developing mobile websites for me, but now I realize why almost every mobile detection script has detection for iPhones (basically, so you can serve them the non-mobile content).  I'm not sure if I'll ever get an iPhone though, simply because everyone I know who has gotten one around here says the coverage is horrible. Plus, I still want to check out a Storm and some other touch screen devices I've seen to see how those compare.  I'd be interested to hear your opinions on which is the best mobile phone for web browsing.&lt;/p&gt;
&lt;p&gt;[polldaddy poll=2418537]&lt;/p&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Tv_CFfc1yDk:Xc1Xti5CEko:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Tv_CFfc1yDk:Xc1Xti5CEko:wF9xT3WuBAs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Tv_CFfc1yDk:Xc1Xti5CEko:wF9xT3WuBAs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Tv_CFfc1yDk:Xc1Xti5CEko:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Tv_CFfc1yDk:Xc1Xti5CEko:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Tv_CFfc1yDk:Xc1Xti5CEko:gIN9vFwOqvQ"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Tv_CFfc1yDk:Xc1Xti5CEko:gIN9vFwOqvQ" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/devtrench?a=Tv_CFfc1yDk:Xc1Xti5CEko:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/devtrench?i=Tv_CFfc1yDk:Xc1Xti5CEko:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/devtrench/~4/Tv_CFfc1yDk" height="1" width="1"/&gt;</description>
<feedburner:origLink>http://devtrench.com/posts/iphone-vs-blackberry-curve-web-browsing</feedburner:origLink></item>

</channel>
</rss>

