creative commons licensed ( BY-NC-SA ) flickr photo shared by Tom Holbrook

Now that the Thought Vectors site is out and running (36 blogs syndicating in, 11 of them from registered students, not bad for the day before class starts), it’s time for a bit more of the techie WTF does that do post, in line with previous posts on such syndication hub sites.

WARNING: This post is long and full of jargon. I would like to explain it in a style to be universally understood, but life on this planet is only so long. And hey, did you think I was writing thix blog all these years for you? Silly reader, this writing is for me me ME ME.

How to Syndicate, Nate (Make a new Feed, Reed…)

In response to the idea that a flow of posts from a large community is more than anyone can digest, I’d been contemplating following up on Martin Hawksey’s brilliant work on the octel site and others to make something more like Google Reader (RI) (/me shakes fist and curses at Google, DAMN YOU ALL TO HELL). My interest in being able to do this clouded what Gardner Campbell reminded me, smacks head on table- a Feed Reader is not a beautiful site, one that leverages the media and payout of sites that get people interested in reading.

So less than two weeks ago, Tom Woodward and I got on a Google Hangout and started going through themes they already had available– they have a subscription to Woo Themes. I have a bit of a love/hate relationship with modern WordPress themes- they have come with a huge amount of overhead to make admin interfaces. I counted and one I used for another project had over 250 files in it- the crusty old Headspace theme here has like 35. They also can make it hard to do customization (let me tell you how inelegant Elegant themes are).

But I am using the Scrollider Woo theme for a client site, and have some good mojo there. We wanted something of a magazine style layout, something that was not just a vertical stack of posts, plus something that had a banner slideshow and portions that could be populated by different tag/categories.

We landed on the Editorial theme and it is the one we are running with now. I found the way it is constructed (parts of templates within “/includes” subdirectories) impossible to set up a child theme– for example:

// Set path to WooFramework and theme specific functions
$functions_path = get_template_directory() . '/functions/';
$includes_path = get_template_directory() . '/includes/';

forces paths to be a parent theme — why oh why do they not use get_stylesheet_uri() ?? So I have gone down the route of working directly off of the theme, which means they should not update it. (IMHO the desire to update themes is way over-rated, I am using one that is like 7 years old and it still works) (and it sure looks like an old theme) (my summer project is a new theme) (maybe).

In short, the Thought Vectors site was not all that different from the previous efforts in having Feed WordPress muscle in the feeds and re-organize them into different views.

But there is always something new in the mix.

The Feed Machine is On

I’ve gone toe to toe with Feed WordPress (FWP) many times, with its idiosyncrasies — all of its data storied in wp_links, the way feeds can go “bad”, the clunkiness of an un-paged admin interface, but after a few years of using FWP, we have an understanding.

My colleagues note the presence of Another Thing That May Be The Great Grail Shaped Hope for Easy Syndication– and it might be…

but I really do not have struggles with Feed WordPress that Tim Owens talks about. I do not doubt it can behave odd, but for the syndication sites I have done now six times– I think I have its number.

In many years of experience with RSS (Feed2JS is, ahem like 12 years old, and still going) I accept that RSS is really not really simple, it is messy. You get a lot of crap in feeds. Bad character sets. Weird markup. Missing data. Just thinking of the spectrum of RSS as one simple thing is… well too simple.

Let me repeat, RSS on a big scale gets messy, especially if you plan to accommodate any platform.

There are thing I wished were easier in FWP, but the experience that It Works (mostly) keeps me in the game. We have over 700 feeds pumping into ds106. Well worth following is the technology used by link farms. But I am not married to any tool, and am interested in poking around with the new kid.

But not for this site.

The harnessing of Feed WordPress, the Tao of Feed WordPress if you will, is understanding how to organize the flow. Otherwise, what you get is just a long train of posts.


creative commons licensed ( BY-SA ) flickr photo shared by cogdogblog

And this is the feature I am not sure I have seen in other tools, to attach categories and tags to incoming feeds. What I have done in every syndication project since ds106 is the following:

  • Convert all tags and categories on incoming feed content to TAGS on the syndication site. This means all of the ways people organize content on their own site, is put into a tag cloud, and allows for ad hoc organization (e.g. if you ask your community to tag or categorize all their posts related to Pink Hair Ponies as pinkhairpony then you can have a URL that dusplays all such syndicated posts).
  • Use Categories on the syndication site to organize content authored there. This means you can create a local structure for announcements, assignments, etc that does not conflict with syndicated stuff.
  • Use Feed WordPress to add categories and/or tags to incoming content. This is where you create a means to provide subset views of syndicated content, like a category for all open participants, or for students in a section, or for just bloggers you like. What this means is Feed WordPress can put additional tags/categories on incoming content, at a universal and at a per feed level.

I start by setting up the default FWP settings, under Categories & Posts, I set the options to move all incoming tags and categories to be tags inside the syndication site.

fwp-cats-tags

Then I also set up a category (“Vectorized”) AND a tag (“syndicated”) to be applied to every syndicated feed (just in case I need use down the line)

categories

Just as a Way I Do Things, the “Vectorized” one is the parent category for all my syndicated content, and is also the default category in WordPress (Formerly Known as Uncategorized).

So now, I back up to describe the structure of the Thought Vectors community; every participant has a blog of their own. We have for blogs

  • Open Participants
  • Enrolled students in six sections of UNIV 200
  • Faculty who each teach one of those sections of UNIV 200
  • Staff or maybe even other students.faculty at VCU

I tried a go at gliffy to show the parts of the ecosystem

(click image to see full sized glory)

(click image to see full sized glory)

All of the pentagram shapes (5 sided like a baseball home plate if you forgot geometry) are people from VCU- UNIV 200 students (yellow), UNIV 200 Faculty (green), and others (blue). Purple circles are open participants.

RSS provides the content for everything copied into the thoughtvectors.net site, as managed by Feed WordPress. All posts from Open participants are added to a category; all UNIV 200 students are in a category, and the same posts can be added to a category just for one section. The UNIV 200 instructors each have a personal blog for posting (in a category); plus the teacher of Section 008 has her posts also appearing in the category for section 8.

The structure I set up for Thoughtvectors uses category hierarchies, used in menus, in the theme, and in the footer– as listed

categories-all

  • Vectorized (category added in FWP, all syndicated sites)
    • All Blogs (category added in FWP to all syndicated blogs)
      • Open Participants (category added in FWP to all syndicated blogs from people self identified as open participants)
      • VCU (category added in FWP to all syndicated blogs from people self identified as being affiliated with VCU)
      • UNIV 200 Faculty (category added in FWP to all syndicated blogs for faculty teaching UNIV 200)
      • UNIV 200 Students (category added in FWP to all syndicated blogs from students enrolled in one of the six sections)
      • Section 005 Ryan Cales (category added in FWP to all syndicated blogs from students and instructor for Section 005)
      • Section 006 Jessica Gordon (category added in FWP to all syndicated blogs from students and instructor for Section 006)
      • Section 007 Jason Coats (category added in FWP to all syndicated blogs from students and instructor for Section 007)
      • Section 008 Bonnie Boaz (category added in FWP to all syndicated blogs from students and instructor for Section 008)
      • Section 009 Gardner Campbell (category added in FWP to all syndicated blogs from students and instructor for Section 009)
      • Section 010 Jon Becker (category added in FWP to all syndicated blogs from students and instructor for Section 010)
      • VCU Faculty and Staff (category added in FWP to all syndicated blogs from people self identified as being affiliated with VCU beyond UNIV 200)

I also have Feed WordPress set up to add a “blogged” tag to all syndicated blog posts (since we are also bringing in some non blog information from twitter and diigo); this is used by the editorial theme to populate the top 4 recent items and the 6 ones that show up at the bottom.

I did all this manually to get the site set up; but now in operation this is all managed by a Gravity Form and a pile of duct taped code (see below).

Got Icons?

Because this is a theme that uses featured images, we deployed two plugins to make this featured images work. The trick is that for WordPress themes to display featured images, that nearly always have to be ones in the local install. Because we are syndicating in posts, all of the media live elsewhere.

Thus we use the Feed WordPress Advanced Filters plugin, which has a number of things that can help modify syndicated content, but the image filter is used to generate copies of all remote images as media in the local install. Once enabled, this plugin (actually a plugin that is a plugin to Feed WordPress) adds a setting to the FWP Posts and Links setting

fap

Yes, we do end up with a ton of other media, but this also comes in handy down the line if the blog disappears, as another feature of Feed WordPress is unsubscribing and setting the content to point to local copy versions.

We also use the Auto Post Thumbnail plugin which makes a featured image out of the first image it finds, if one is not specified (although this is also a part of our Woo theme, not quite sure why I added it, but hey, everything works). There are a few shortcomings, like we have some themes that have invisible GIFs in the layout or sometimes the first one found is a facebook like icon from the sidebar.

This (ahem) might be an encouragement for people to use images in their posts! Ya think?

And the last thing that helped is that for the Woo Themes, under Theme Framework Options, I was able to define an icon to be used if no featured image was provided.

Feed the Others

Twitter is a key part of the open experience, and we’ve been lighting up the #thoughtvectors hashtag for weeks. We are running the Magically Delicious Twitter Tags Spreadsheet by [Sir?] Martin Hawksey, and I have them all embedded into local pages on the site– the most insanely useful one to me is the Twitter Explorer, where you can really try to make sense of the connections, and even view back one person’s conversational history.

tags-explorer

I still think it is useful to also have the tweets inside the WordPress database, just in case down the line we figure a way to do some analysis or visualization from the tweets and blog posts together (they should be related by person and time).

So as I have done before, I use a labnol script that converts a hash tag search into RSS (shakes fist at twitter for nuking RSS feeds), so I can bring it into Feedwordpress. While there is not a big presence to show them on the site, I do use a technique I have done before to display tweets as tweets– the RSS feed gives you the text of the tweet as the title and the item, but all we need is the link to th tweet, and modify the template to use WordPress oembed function to display.

To manage this, all posts from the twitter feed are put in the Twitter category (the touch if Feed WordPress Category settings).

For example, in the archive.php template, we do a check on each item to see an item in the category (or it is the category itself), and rather than using the typical display we use the oembed function:



#thoughtvectors tweet

(normal template display stuff)

I ended up doing some styling bits and template nudging for the archive of the twitter category (again adding the oembed, but also making it full width (3 tweets wide), and changing the default number of posts per query loop to be a multiple of 3.

tweet archive

The other syndication source (for now) is diigo where we expect students to be marking up resources. My first impulse was the hope we could get an RSS feed site wide for everyone who used the thoughtvectors tag in diigo; alas the service does not provide that. I was dipped too much in delicious, which sad as it goes, I am not feeling all that trusting of anymore.

Our compromise is to get the feed from a diigo group we set up which we are syndicating directly in via http://thoughtvectors.net/category/vectorized/resources/.

Considering the goal of the course, this is not a horrible compromise. I would think course participants ought to tag in their own diigo account and maybe set up a widget or syndicate to their own site. I see it as a worthy practice for people not to share everything they bookmark, but the best resources they find in the course of their research by sending them to the group.

Oh Feed, Where Art Thou?

A big part of the mix is how to get people’s blog feeds, this being the holiest of holy grails. Having cleaned up after submissions in the signup form at ds106, and having done it via collecting via a Google Form, I feel like a lone wolf in howling how messy this gets.

Let’s put it this way, if we are syndicating everything from a site, it is simple to write a script to grab a site wide RSS feed. That works (and we are using it).

But it gets an order of magnitude chaotic when you ask people to share a feed for a category or a tag on their site. If you know everyone is using WordPress or tumblr (as we do in Project Community), you can make uniform instructions. When feeds can be anything, this is what you have to deal with (and having hand checked over 600 feeds for ETMOOC I have some experience to speak from):

  • Blogger uses “labels” as something like a tag/category. Yet, in the source there is no discoverable META tag for the RSS feed.
  • And the same goes for WordPress. I defy you to find me where in the source the RSS feed for a Tag/Category feed exists- you get the RSS feed for the entire site or the comments.
  • And it’s not just a matter of saying to someone “Just find the URL for your category/tag archive and add ‘/feed’ like http://cogdogblog.com/category/pinkponies/feed — this only works for blogs with permalink settings turned on from defaults. Many blogs have URLs for tag/categories like http://cogdogblog.com/?cat=19 which means the feed URL is something like http://cogdogblog.com/?cat=19&feed=rss2 — Deep down I know one could find a way to sort this out from a URL… well its still messy.
  • As I just found out today, it also gets messed up when someone uses Feedburner, since all WordPress feed URLs (the ones I might describe how to figure out) get usurped by the general Feedburner feed, and we get all the content syndicated. I believe you can create a secondary Feedburner URL for a tag/category.
  • And freaky Safari as a browser, when you test a feed URL like http://cogdogblog.com/category/pinkponies/feed resolves it as feed://cogdogblog.com/category/pinkponies/feed — and Feed WordPress knows not what to do with it.
  • And heck, people often do not even understand a URL and put gibberish in like http://Idontknowwhatthismeans, or leave off http:// or just drop the “:” or …

In my experience, Feed WordPress does best when you provide it the exact feed URL and do not rely on it to figure it out. The desire is to make this “easy” (cue Todd Conaway’s Easy Button).

But since this is an experience where we want to teach people how the web and networked systems work, I think its better that they get some understanding what RSS is, that the web the see in a browser is not the data that is sent from a server to your computer.

At first I imagined a flow chart, but in conversation with Tom (after making a horrible looking flow chart on a white board), we settled on something more like a choose your own adventure game, with a series of questions that take people down the path to find their feed… or as Tom does well, to make it into a metaphor, along with the subtle tangential hyperlinks:

Being of the web often involves weaving together streams of information. Knowing that information can flow like water is important conceptually as you think about how technology might augment your intellect.

The following pages will help guide you towards identifying your individual RSS stream so that it might become a tributary of the great information flow (or so your posts can be like apple pies for whales).

So when I click on the yes response to “I have a blog” button you get and animated affirmation.

i have a blog

The main split is for people who have a blog and want to syndicate in a portion, we spell out the various ways they should construct their feed. More or less they should find the URL to their tag/category, figure out how to append or add something to get the feed, URL, and above all else, TEST THE URL.

We do throw in the mix some detection for people who indicate they will use their entire blog, what I call the Magic Box

magic-box

This is a similar approach we used on the ds106 signup — some code I played with, Martha Burtis and Martin Hawksey both refined, to find a feed from a blog main url.

This is a wordpress page with a modified template that allows to act like a normal web form, I have one field named “blogurl” (the text input for the URL), and do some error checking on the input.

$blogrss = feedSearch( $blogurl );

The work is done by a function in my functions.php. What it does is to fetch the source HTML for the given URL via the curl function and uses some Xpath matching to try and find the patterns for a RSS2 or an Atom Feed.

/* ----- find an RSS feed for a given URL */
function feedSearch( $url ) {

  // via Martin Hawksey via from Alan Levine (@cogdog)
    if ( $html = @DOMDocument::loadHTML( file_get_contents( $url ) ) ) {
  
        $xpath = new DOMXPath($html);
        $results = array();
                 
      // find RSS 2.0 feeds
        $feeds = $xpath->query("//head/link[@href][@type='application/rss+xml']/@href");
        foreach($feeds as $feed) {
            $results[] = $feed->nodeValue;
        }
 
         // find Atom feeds
        $feeds = $xpath->query("//head/link[@href][@type='application/atom+xml']/@href");
        foreach($feeds as $feed) {
            $results[] = $feed->nodeValue;
        }
        
        // we have somethng
        if ( count( $results ) ) {
        
          // we assume (badly) that the first result is the blog feed
          return $results[0];
        } else {
        
          //oops return an error
          return -1;
        }
    } else {
      return -1;
    }  
}

It does make the assumption that the first feed found is the main feed for the blog.

The aim for our setup is to make sure people can find the proper RSS feed for their site. From out first 40 submissions, we seem to be successful about 85% of the time.

Getting My Feed into the Machine

And now the complicated part! Is anyone still out there?

If you have your feed figured out, then you can head to the Syndicate Here form, what we set up so let people add their feeds directly to Feed WordPress. It’s a slight extension for what Martha Burtis rigged up for ds106, using Gravity Forms to collect the info, and some functions to write the data to the WordPress links table.

In a perfectly coded world, I would be able to provide this to you as a nifty plugin, and maybe some day that will happen. But this was a case of get it done, because students needed to get this info before classes start (which is technically tonight).

When you add a feed to the site, it is associated with a WordPress user account, but the person filling out the form never knows it, nor needs to log into the site. We do it to associate a user with the feed. To make unique usernames, we ask for a twitter user name (besides we want people using twitter), and we use it as the wordpress username when processing the form.

The script adds a few more fields to the typical WordPress user profile, these provides extra fields we may (or may not) user later.

/* ----- add custom user profile fields */
add_filter('user_contactmethods', 'tv_modify_profile');

function tv_modify_profile( $profile_fields ) {

	// Add new fields
	$profile_fields['blog'] = 'Thought Vectors Blog';
	$profile_fields['blogfeed'] = 'Thought Vectors Blog Feed';
	$profile_fields['geolocation'] = 'Geographical Location';
	$profile_fields['twitter'] = 'Twitter User Name';
	$profile_fields['org'] = 'Organizational Affiliation';
	
	return $profile_fields;
}

So when Giulia Forsythe signed up, a user account was created using her twitter handle as the user name:

profile contact field

Maybe down the line we might try some geolocation (thought “Canada” is pretty big). But the thing we needed was a way to create user accounts in our form processing function. I will break this down into segments. What we need to end up doing is creating a link in the WordPress collection, and writing data to the notes field in a specific format, e.g.

link fields

This data for Laura Gogia’s blog makes sure we have the RSS Feed, an association with a wordpress user account, the default “blogged” tag, and some assigned categories (one for All Blogs, one for being from VCU, and one for being a VCU Faculty/Staff).

The nifty thing is Gravity Forms can do logical display of fields; so if a person selects “open” as an affiliation, the Organizational Affiliation appears (since for VCU we know what it is); and if they indicate they are a UNIV 200 student, we can toggle open the radio buttons for sections.

First we set up a hook and a function to respond to when Gravity form ID 1 is submitted.

add_action("gform_after_submission_1", "add_blog_to_fwp", 10, 2);

function add_blog_to_fwp( $entry, $form ) {
	global $wpdb; // cause we need to go to the database directly
	
	// set filters aside for input
	remove_filter('pre_link_rss', 'wp_filter_kses');
	remove_filter('pre_link_url', 'wp_filter_kses');

The global variable is used for calling the database directly, and the filters put aside are something needed to write to the notes field as needed.

Next we do some data setup. We create a variable to hold the data that represents the default Links category Feed WordPress uses (usually “Contributors”), and extract the category ID into $contrib_category. We store the value for the form (ID 4) and save it as $twittername (plus strip out a “@” just in case they did not read the instructions to leave that off)

	// Get the link category Feed WordPress uses to store feed data
	$fwp_link_category = get_terms('link_category', 'name__like=Contributors');
	
	// get the correct term id for the link category
	$contrib_category = intval($fwp_link_category[0]->term_id);
	
	// we will use twitter handle as a user name
	$twittername = trim( $entry[4] ); 
	
	// just in case they put an @ in front, take it out
	if ( $twittername[0] == '@' ) $twittername = substr($twittername, 1);

Now we set up all of the variables we need to write a query to the database that will create a new WordPress user based on the form data

	// set up array to create a new WP account; password is randomized- user never needs
	// to log in, shhhhhhh it's a secret
	$userdata = array(
		'user_login'    => $twittername,
		'user_pass'		=> wp_generate_password( $length=12, $include_standard_special_chars=false ),
		'user_email'	=> $entry[2],
		'display_name'	=> '@' . $twittername,
		'first_name' 	=> $entry['1.3'],
		'last_name' 	=> $entry['1.6'],
		
	);
	
	// create account
	$user_id = wp_insert_user( $userdata );

If $user_id is not a an error object, we can proceed, first by updating all of the user extra profiled feeds we created above. I’ve added a replace just in case their feed URL is in the feed:// format. This code is rather tightly tied to the gravity form field IDs (I guess I could re-write then to use the form field names, duh)

	// error check and bomb out, should only be if username exists
	if ( !is_wp_error( $user_id ) ) {
	
		// Safari browsers convert RSS feeds to feed://, so replace it if its in the string
		$feedurl = str_replace("feed://", "http://", trim( $entry[5] ));
		
		// update our custom meta data fields, these are ones created specifically
		// for this site, your mileage and use should vary
		update_user_meta( $user_id, 'blog', trim( $entry[3] ) );
		update_user_meta( $user_id, 'blogfeed', $feedurl );
		update_user_meta( $user_id, 'geolocation', trim( $entry[6] ) );
		update_user_meta( $user_id, 'twitter', trim( $twittername ) );

Next we have to assemble the string for the notes field that indicates the categories that should be added to all posts from this feed. The format us each one is represented in the form:

{category#XX}

where XX is the ID number of the post category (and they will be later separated by “/n”). We do this by building an array of all the values needed. “{category#23}” is added to every feed (it is the All Blogs) category; then we test the form values to apply the Open Category ({category#24}) and also update the profile field for the value if the organization.

The logic continues to separate out the UNIV 200 students, and if that is indicated, the {category#xx}” values for the section are actually coded into the form (more Alan laziness).

		// start with an array to hold categories for the Links note field
		// in the fun quirky format FWP uses
		$catids[] = "{category#23}"; // add Blog category to all feeds
	
		// Walk through the affiliations
		if  ( $entry[7] == 'open' ) {
		
			// open participants?
			$catids[] = "{category#24}"; // add category for Open Participants
			update_usermeta( $user_id, 'org', trim($entry[8]) );
	
		} else {
			// VCU Participants
			$catids[] = "{category#70}"; // category for VCU Participants
			update_usermeta( $user_id, 'org', 'VCU' );
		
			if  ( $entry[7] == 'vcu' ) {
				$catids[] = "{category#33}"; // category for VCU Faculty, staff
			
			} else {
					$catids[] = "{category#26}"; // category for UNIV Student
					
					// for UNIV students, we add a category, the code is in the Gravity
					// form because I was lazy on writing a swtich STATEMENT_TRACE
					$catids[] = $entry[10];
			} // end if for VCU participants
		} // end if for VCU

Now we can build the rest of the string the notes field needs, again, it its particular format required by Feed WordPress- we do the author association with the new author id created above, we add a tag for all, and the categories we just assembled (using some PHP to join the array elements with ‘\n’ as separators).

		//build the link notes with the user name created for this blog
		$link_notes = 'map authors: name\n*\n'. $user_id . "\n";
	
		// add a tag to all syndicated blogs
		$link_notes .= 'tags: blogged' . "\n";
	
		// add categories to the link notes
		$link_notes .=  'cats: ' . implode( '\n' , $catids) . "\n";
		
		// flag to add tags and categories
		$link_notes .= 	'add/post_tag: yes' . "\n" . 'add/category: yes' . "\n";

And at this point we can call a function that creates the WordPress Link, and after that update the link with the data for the notes field (this has to be done by a mySQL custom query).

		$new_link = array(
				'link_name' => trim($entry[3]),
				'link_url' => trim($entry[3]),
				'link_category' => $contrib_cat,
				'link_rss' => trim($entry[5])
				);
		if( !function_exists( 'wp_insert_link' ) )
			include_once( ABSPATH . '/wp-admin/includes/bookmark.php' );	

		// add the new link
		$linkid = wp_insert_link($new_link);
	
		// clean the link notes
		$esc_link_notes = $wpdb->escape($link_notes);
	
		// update the notes in the links
		$result = $wpdb->query("
				UPDATE $wpdb->links
				SET link_notes = \"" . $esc_link_notes . "\" 
				WHERE link_id='$linkid'
		");

The last thing is a really useless error message if the WordPress user was never created.

	} else {
		// a most useless error message for user creation
	   	$error_string = $user_id->get_error_message();
   		die ('ERROR CONDITION RED: ' .  $error_string);
	}
}

And that is all there is to it. Easy, right? Bueller? Bueller?

Understanding how Feed WordPress runs from the links info is useful, especially because the function to change a link’s URL from the Feed WordPress interface never works (“are you sure you want to do this”) with no buttons. So fixing the feed URL is as simple as editing the field in the link.

Can I Have Some Butter With that Feedroll?

I like having the site, and the category archives displaying in the sidebar a list of all blogs in that category, a feed roll. I’ve modified code I did first for ds106 to provide a shortcode that does this for a sidebar widget.

It also generates the full list on the page that lists all blogs, just with this shortcode (23 is the ID for the category All Blogs):

[feedroll category="23" show="all"]

all blogs

For the widget, I hoped to do one shortcode that would work on all category archives (on ds106, I need to make a custom one for each different group of blogs)- that shortcode is really easy

[feedroll]

I like using the Visibility feature of the Jetpack plugin, which allows me to provide logic for the places a blogroll appears, in this case I just hide it if you are on the All Blog list above (it would be redundant)

visibility widget

The widget has two modes; on a category archive page, it will list all blogs in that category, for example the sidebar on the category for All UNIV 200 Students (for now) lists all blogs, and a count of how many combined posts there are

student blog roll

This will of course get too long (we have 120 students), so by setting the mode of the widget

[feedroll show="random"]

We can get the functionality that it shows on non-categopry pages- an indication of how many syndicated blogs there are on the site, and a random subset of 10 blogs from that group:

all blog roll

This took some crazy logic I will not bore the 1 person who might actually be reading this. The way it works is that it figures out what category id it should look for, and runs a custom mySQL query looking for it in the Links Notes field in that pattern desdcribed above.

IF you are really manic, here is the entire code for the shortcode:

/* ----- shortcode to generate a Feed WordPress feedroll for a given tag */

function get_feed_count( $offset = 0, $link_cat = 'Contributors') {
	$links = get_term_by( 'name' , $link_cat, 'link_category' );
	if ($links) {
		return ($links->count);
	} else {
		return 0;
	}
}

add_shortcode("feedroll", "tv_feedroll");  

function tv_feedroll( $atts ) {  
	global $wpdb;
	global $cat; // so we can get the current category
	
	// Get the value of any passed attributes to our function
	// $category is either passed or assumed from being on an archive page 
	//		default is the parent category for all feeds
	// $show defaults to listing all feeds for display in a sidebar; if the list is long
	//		pass a value of "random" to list a subset chosen randomly; "all" to list all on a PAGE_LAYOUT_ONE_COLUMN
	// $limit = how many to list on a random subset
	
 	extract( shortcode_atts( array( "category" => "23", "limit" => "10", "show" => "sidebar" ), $atts));  
 	
 	if ( is_category() ) {
 		// set to correct id if we are on a category archive (e.g. general category widget)
 		
 		$catid = $cat;
 	} else {
		// get category ID if not passed as a value (we can haz string names for a param)
		$catid = ( is_numeric ( $category ) ) ? $category : get_cat_ID( $category );
 	}	
 	
 	// A bit of gymnastics- for a sidebar where we do not want them all (default category)
 	// override for the random subset
 	if ( $catid == 23 and $show!= "all" ) $show = "random";

 	// keep a reference for the current category for an archive page
 	$mycat = get_category($catid);
 
 	
 	if ($show == "random") {
 		// setup for displaying a random subset of feeds
 		$orderby = 'RAND()'; // mySQL order to pick random feeds
 		$limit = "LIMIT 0, $limit"; // limit to set amount
 		
 		// uh oh,  hard wired link to see the full list. Make the link to a page that 
 		// uses the shortcode to list all (or empty this string out)
 		$footer = '

See All Blogs

'; } else { // normal mode to list all blogs in a category $orderby = 'wpl.link_name ASC'; $limit = ''; $footer = ''; $suffix = ' from the following blogs:'; } // custom mySQL query to get subscribed blogs from the links table // because FeedWordpress stores stuff in the link notes // the linked WHERE condition makes sure there is at least one syndicated post // from a given feed $custom_query = " SELECT DISTINCT wpl.link_name, wpl.link_url, wpl.link_description FROM $wpdb->links wpl, $wpdb->postmeta wpm WHERE wpm.meta_key='syndication_feed_id' AND wpm.meta_value = wpl.link_id AND wpl.link_notes LIKE '%%{category#" . $catid . "}%%' ORDER BY $orderby $limit "; // run run run that query $feedblogs = $wpdb->get_results( $custom_query ); // bail if we got nothing if (count($feedblogs) == 0 ) { $content = "No blogs found for '" . $mycat->name . "'"; // we got feeds! } else { if ($show == "random") { // for a random subset we want to reference a count of all blogs on the site; // in this site we have 2 feeds that are not blogs, so pass that as a parameter // (more hard coding specific to this site, sigh) $suffix = ' from ' . get_feed_count(2) . ' total blogs syndicated into this site. Ten random ones are listed below: '; } else { // let's be grammatically correct for only one blog $plural = ( (count($feedblogs) == 1 ) ) ? '' : 's'; $suffix = ' from ' . count($feedblogs) . ' blog' . $plural . '. '; } // Yikes, we use the "Count Posts in a Category, Tag, or Custom Taxonomy" plugin to get a total post count $content = '

Thought Vectors includes ' . do_shortcode('[cat_count slug ="'. $mycat->slug . '"]') . ' total post(s) syndicated for ' . $mycat->name . " $suffix

"; //start the output $content .= "
    \n"; if ($show == 'all') { // output each item as a list item, title of blog linked to URL, and a description foreach ( $feedblogs as $item ) { $content .= '
  1. ' . htmlspecialchars_decode($item->link_name) . ' ' . htmlspecialchars_decode($item->link_description) . ' (' . htmlspecialchars($item->link_url) . ')
  2. ' . "\n"; } } else { // output each item as a list item, title of blog linked to URL foreach ( $feedblogs as $item ) { $content .= '
  3. ' . htmlspecialchars_decode($item->link_name) . '
  4. ' . "\n"; } } // clean up after your lists $content .= '
' . $footer; } // here comes the output return $content; }

This function has some potential to be re-coded to be generalized enough to be a plugin.

Maybe.

Would You Like PHP With Your Fries?

I am losing tracks of the other mods I have made- I did a bit of custom CSS to override or hide the formatting (“display:none” is your friend).

Because the excerpts for all syndicated content comes from somewhere else, I added most every where a source credits text. This is done in the theme templates- by using the FWP function is_syndicated() indicates if an item in a WordPress Loop has entered via Feed WordPress, and if so we can insert the source name that is stored in a post’s custom fields:

// show blog source if syndicated
if ( is_syndicated() ) {
 echo 'via ' . 
    get_post_meta($post->ID, 'syndication_source', $single = true) . 
    ''; 
}

WordPress themes like the one we are using to display teasers for posts use a chunk of content called the excerpt a feature built into WordPress. A problem with syndicated content is media will be dropped (e.g. from tumblr) or it has no excerpt (Blogger). So a typical WordPress theme uses this function

In WordPress the default length of an excerpt is 55 words- and in a layout that can vary widely. For a more balanced display, I prefer to generate an excerpt based on character count (and strip out all the HTML so we do not leave broken tags or weird formatting):

function get_character_excerpt( $content, $chars=500 ) {
	if ( strlen( $content ) > $chars ) {
		return ( strip_tags( substr( $content, 0, $chars ) ) . '...' );
	} else {
		return ($content); 
	}
}

This way I can specific in my templates how big/small the excerpt should be using (the function get_the_excerpt() grabs whatever it considers an excerpt, for Blogger it is the whole shebang apparently)

echo get_character_excerpt( get_the_excerpt(), 700 );

Another new trick was a hack to manage the front page sliders- those all come from posts with a specific tag. I wanted to add to the banner an image and a link to the Twitter Explorer. But that is a page.

So what I set up is a way you can create as a post the data needed to generate the banner slide- a featured image, and some text for the excerpt. But there is a custom field you can edit called redirect

custom field

My template hack means that whenever you link to the Post (try it, it’s really just a holder for the slide content), you end up on the URL in the custom field .

This was an edit to the single.php template, which is used to display a single post. The code below comes first before anything else in the template:

ID, 'redirect', true );

// check if the custom field has a value
if ( ! empty( $redirect ) ) {
	// bingo! send us there instead
	 wp_redirect ( $redirect );
} 

  :
  :

(continue with rest of template code)

Doing this was more of a “I wonder if we can do it”) but now I see how we can add a graphic image banner that can be linked to any of the UNIV 200 class sites; each section has their own class size for section specific information from their teacher (we seem to call them “Clubhouses”).

And Now for the Close

I wonder if this is the longest blog post ever hoisted here. Like I mentioned, much of this is for my own documentation- as usual I have rigged something together that may not be completely replicable elsewhere.

But look- we have a pretty gorgeous looking site. We are already syndicating in 43 blogs, 15 of which are students all brand new to WordPress.

And the work for them, and the teachers is just beginning! It’s going to be fun/interesting to see how this plays out. Hopefully worrying about the server does not keep Tom up at night.

Syndication sites are no cake walk. They will rarely be push-button magic box. But if you can get close to the machine and not burn your hair, you can do quite a bit.

If now, you know where to find me.

(Hunched over fixing my sloppy coding).

activate

Thought Vectors Activate! (and Syndicate!)

If this kind of stuff has value, please support me by tossing a one time PayPal kibble or monthly on Patreon
Become a patron at Patreon!
Profile Picture for CogDog The Blog
An early 90s builder of web stuff and blogging Alan Levine barks at CogDogBlog.com on web storytelling (#ds106 #4life), photography, bending WordPress, and serendipity in the infinite internet river. He thinks it's weird to write about himself in the third person. And he is 100% into the Fediverse (or tells himself so) Tooting as @cogdog@cosocial.ca

Comments

  1. Ah! That is why I was sent on an adventure to find and test my feed! It worked. And I learnt something about backstage on the internet show! And I loved the gif of course.

    I did not read the whole thing, no surprise there. But I read enough to marvel at how little attention I pay to what makes the magic happen. i just moan when it is not smooth and forget that there are many Alans and Toms everywhere tackling this stuff to keep it going. I am glad you write this stuff up, it helps me understands its complexity even if I know that I will never have the kind of patience you both have to do it. Each time I give it time, I learn a little more and I am grateful for that.

    The site looks awesome and i love the community diagram.

    Thank you both for loving this stuff so much and sharing your workings with the rest of us. Even if you only wrote it for yourself! Who are you kidding? :O)

  2. Astonishing, wonderful, bravo. “Thanks” can never be enough. And to think this journey began for me with your face floating above the auditorium in New Orleans in 2005.

    And now I’m at a loss for words. Everything Mariana and Tom said goes for me, too. With love.

Leave a Reply to Gardner Cancel reply

Your email address will not be published. Required fields are marked *