x

Guerrilla Gardening the Institutional Web

September 4th, 2009
post #142 

Something else was going on in Colchester around the time of IWMW 20009. While delegates of the Institutional Web Management Workshop were hearing the mantra ’seek forgiveness rather than permission’ for any improvements we’d like to make to our institutional web provision,  The Human Shrub was hard at work with some unapproved upgrades of his (or her) own.

Inspired by the guerrilla gardener I’ve decided to take some direct action on an area of our site. I’m going to tell no-one, and work by cover of darkness. I’ve yet to decide on an outfit.

The aim is to use spare time and all available methods to improve the look and feel, user interface and usability of the area in a non-invasive way, avoiding all the usual time constraints. By the end I hope to have something suitable to replace or update the area that all stakeholders will find difficult to refuse.  To do this:

  • All work must be carried out on breaks, out of hours or overnight
  • No live content will be touched, proof of concept will be devised & created as alternate services
  • Extant environment and systems will be respected – that means working with the CMS, with the means of editing and deployed using the normal methods
  • Ease of integration or implementation a major determinant of any approach (so no recreating the whole site as a Symfony plug-in)
  • As with any unofficial, unbidden and unapproved endeavour, the goals will shift & adapt as and when.
  • Horticultural metaphors will abound.

Putting IWMW2009 into action

August 10th, 2009
post #140 

I am not alone in being fired up the by plenaries, parallels and general fervour(?) that the Institutional Web Management Workshop inspires.
My first act towards devil may care guerilla HE web improvement begins today, as I re-present  – to members of our Marketing Team – some of the main concepts discussed by Michael Smethurst and Matthew Wood from BBC Music in their plenary on how they make websites.

My audience has been primed with the knowledge that they don’t start with wireframes and Photoshop mock-ups, so there’ll be plenty to talk about. This will hopefully inform an upcoming reworking of our student centred web provision. I’m also arming myself with Mr Boag’s Making your killer applications… killer! slides – covering everything from Desktop convergence to thinking in apps, not pages, and the challenges of bringing these methods into the HE web.

A Daily-Symfony-Quick-Setup-Zen-Cheatsheet

July 2nd, 2009
post #137 

Making the transition to Symfony 1.2 and Doctrine all at once was never going to be easy. As Doctrine is the future of symfony and I have a distinct Propel addiction, the following steps (based on the early stages of the excellent Jobeet tutorial) will take no time at all and can be practised often to help cement the process in mind until it’s second nature.

This is no substitute for (and will make little sense without first reading) the Jobeet tutorial, nor the documentation. This is just my daily-Symfony-quick-setup-zen-cheatsheet. I hope in time to be doing this one-handed in my sleep while vaccuuming the stairs. Copy+Paste strictly out of bounds.

If you choose to use this and repeat it often, you’ll have setup your web server config’ on your development setup ready to run this, so those steps are omitted.

Posted here in a bit of a rush to respond to Jwage’s request , I hope they live up to expectation, and that someone finds them useful. I am bound to have made some errors, some omissions or not been concise enough, please let me know.

Create The Project

  • mkdir <path_to_local dev>\newsymfonytest
  • cd <path_to_local dev>\newsymfonytest

From now on<path_to_local dev>\newsymfonytest is your <project> directory

  • php <path_to_symfony>\data\bin\symfony generate:project newsymfonytest
    • Note that this creates an absolute path to Symfony in <project>/config/ProjectConfiguration.class.php which you should update.
  • copy the sf folder from  <path_to_symfony>\data\web\ into <project>/apps/frontend/web or alias it in your server configuration Alias /sf “<path_to_symfony>\data\web\sf”
  • Now Symfony is linked from your current location, the <project> root, test local access to Command-Line Interface with php symfony cc
  • Check the application has been created by visiting in browser

Setup Doctrine Database

  • Replace the setup function in <project>/config/ProjectConfiguration.class.php
public function setup()
{
  $this->enablePlugins(array('sfDoctrinePlugin'));
  $this->disablePlugins(array('sfPropelPlugin'));
}
  • Publish any plugin assets: php symfony plugin:publish-assets
  • Clear the Cache php symfony cc
  • Remove Propel structure, create Doctrine structure:
    • rm config/propel.ini
    • rm config/schema.yml
    • rm config/databases.yml
    • mkdir config/doctrine
  • create database in MySQL: mysqladmin -u root -p create newsymfonytest
  • << enter password when prompted or omit -p if you have no password set (shame on you!) >>
  • setup the YAML schema in <project>/config/doctrine/schema.yml

Here’s my sample schema.yml, lifted from the Jobeet tutorial:

# config/doctrine/schema.yml
SampleCategory:
  actAs: { Timestampable: ~ }
  columns:
    name: { type: string(255), notnull: true, unique: true }

SampleItem:
  actAs: { Timestampable: ~ }
  columns:
    category_id:  { type: integer, notnull: true }
    type:         { type: string(255) }
    is_activated: { type: boolean, notnull: true, default: 0 }
    email:        { type: string(255), notnull: true }
    expires_at:   { type: timestamp, notnull: true }
  relations:
    SampleCategory: { onDelete: CASCADE, local: category_id, foreign: id, foreignAlias: SampleItems }
  •  Generate a new Databases.yml:

php symfony configure:database –name=doctrine –class=sfDoctrineDatabase “mysql:host=localhost;dbname=newsymfonytest” <mysqluser> <mysqlpass>

Build!!!

  • php symfony doctrine:build-model
  • php symfony doctrine:build-sql
  • php symfony doctrine:insert-sql
  • php symfony doctrine:build-forms

Add Sample Data

Create fixture files:

Here’s my sample <project>data/fixtures/categories.yml, again lifted from the Jobeet tutorial:

SampleCategory:
  design:
    name: Design
  programming:
    name: Programming
  manager:
    name: Manager
  administrator:
    name: Administrator

Here’s my sample <project>data/fixtures/items.yml, curiously similar to one from the Jobeet tutorial I’ve said so little about.

SampleItem:
  job_sensio_labs:
    SampleCategory: programming
    type:         full-time
    is_activated: true
    email:        job@example.com
    expires_at:   '2010-10-10'
  • Populate with php symfony doctrine:data-load

Generate first app

  • php symfony generate:app –escaping-strategy=on –csrf-secret=1sTh15r34l1y53cur3 frontend
  • Visit the site root you set up in your server configuration in your browser

Generate first module

  • Then, using the format:
  "php symfony doctrine:generate-module --with-show --non-verbose-templates <appname> <modulename> <modelname>"

php symfony doctrine:generate-module –with-show –non-verbose-templates frontend sample SampleItem

  • Visit the module in your browser
  • Rinse and repeat

Background Animations in Script.Aculo.Us

November 12th, 2008
post #135 

Inspired by Jonathan Snook’s article on animating backgrounds using Jquery, I had a snoop around in Script.aculo.us for the equivalent methods to create moving background images. It wasn’t long before I hit a wall with the Effect.Morph method and its inability to parse the CSS values for background-position.



Effect.Morph simply examines current CSS values and calculates new ones, iterating through a number of transforms according to the duration of the morph. Colour values are handled appropriately, but for positioning only a single value is anticipated. As the second value of background-position is never parsed, you’re limited to horizontal animation.

see a demo of the problem.

So I’ve created an extension, similar to Alexander Farkas’ for JQuery, to manipulate background-position both vertically and horizontally using the same syntax as Effect.Morph.

See it in action on Horizontal and Vertical background animations and Vertical only.

Using the Effect.Morphbgpos extension

Include in the <head> the Prototype and Script.aculo.us libraries as usual. Download the extension and include it after the main libraries:

<script src="bgposeffect.js" type="text/javascript"></script>

Jonathan did a great job describing his HTML and CSS markup (including how to show the final states of the animation using CSS just in case Javascript is not present) so I won’t repeat it all here. Suffice to say this is very similar: an unordered list with an id, containing three items, containing only links.

<body>
...
<ul id="a">
	<li><a href="#">Rivera</a></li>
	<li><a href="#">Miro</a></li>
	<li><a href="#">Varo</a></li>
</ul>
...

Then (somewhere after the list) include the code observers that restyle your links on mouseover and mouseout:

<script type="text/javascript">
$$('#tabs a').each(
	function(s) {
		s.observe('mouseover', function(s){
			this.setStyle( {backgroundPosition: "0px 5px"});
			new Effect.Morphbgpos(this, {
			  style: 'background-position:0px -40px;color:#cc0000',
			  duration: 4.3
			});
		});
	 	s.observe('mouseout', function(s) {
			this.setStyle( {backgroundPosition: "0px -40px"});
			new Effect.Morphbgpos(this, {
			style: 'background-position:0px 5px;color:#c0c0c0',
			duration: 4.3
			});
		});
	});
</script>

Note that in the example each of the observer methods sets the state directly before animating it. Mouseover begins from the original state set in the CSS while Mouseout sets the finished state (as in the CSS link hover state ) before animating back to the original state.

How it works

Very simple. Effect.Morphbgpos is a modified version of Effect.Morph that anticipates having to handle two sets of pixel values. It reads the current states into x and y variables, manipulates them and writes out the appropriate CSS, repeating until the final state is reached.

Handling Other Effect.Morph CSS properties

The extension will pass any CSS that isn’t a background-position property to a new instance of Effect.Morph.

You should be able to replace all Effect.Morph calls with Effect.Morphbgpos, and then simply find+replace them when this functionality becomes available in a future version of the framework.

Limitations

This first version only handles explicit background-position statements, using pixel values, and duration is the only supported option.

As it’s only extending Script.aculo.us by a fraction it seems to be robust across the browsers I’ve tested.

Download & usage

Download the js file here (or here as text). Use just as you would Effect.Morph by settings CSS property-value pairs, and a duration.

RSS take-up peaks at 11pc

October 21st, 2008
post #132 

I won’t be spending $279 to find out the details:

Nearly half of interactive marketers use RSS, but consumer adoption has only reached 11%. Of the consumers who haven’t adopted RSS, most don’t understand how RSS is relevant to their lives and the way they seek information. If marketers expect to reach a critical mass of consumers by using content syndication, then they must take on the burden of education.

[source: forrester.com...150,00.html]

So I wonder how many people knew they were using RSS, and how many accessed syndicated material without realising the nature of it’s origin. Yahoo Pipes for instance, mashups etc.

Were Podcasts included or excluded?

Hard found gains in Symfony

September 2nd, 2008
post #126 

My first production Symfony application is a newletter manager and sender. This gave me a few headaches that I couldn’t easily find solutions for in the Docs. In the end trial, error and other sources came up with some gems that kept things moving.

Assigning complete module output to a variable

sfContext::getInstance()->getController()->»
getPresentationFor('module','action');

This is pretty useful, dropped into your Action this retrieves the fully rendered (layout, template, content) output of another Action/Module. Many of the email examples recommend putting the content you wish to send out into a partial or component and show how to grab it for variable assignment, but this will take a whole page you might want to email ‘as is’. I use it retrieve a current newsletter page as it is would be rendered for the web so I can drop it into an email.

Flexible but full Absolute URLs to assets

mymodule:
  stylesheets:    [main , 'http://mysiteDotCoDotUK/path/to/this.css']
  javascripts:    ['http://mysiteDotCoDotUK/path/to/that.js']

The books don’t seem to mention it, but you can use absolute URLs in your view.yml for embedding stylesheets and javascripts. So you can set granular stylesheet and script settings down to the module while still producing absolute links to them. When your assets also use the absolute=>true boolean options in Link and Asset Helpers, then you have dynamically generated fully standalone output. I’ll be using this to make sure email newsletters find their supporting content.

With this, I can provide the editor interface, management and preview options, a live copy of the current newsletter and archive of old ones on the web, and share the very same content in mails to subscribers.

Mixing Object and Form Helpers in Symfony

August 21st, 2008
post #125 

Being new to Symfony I’m still getting my head around some of its paradigms. Two months with the manual before embarking on any development taught me that it was worth pursuing, but there’re always areas you need to see working.

The Object form helpers looked particularly useful, so for my first production development I aim to use them wherever possible. These helpers allow you edit objects directly, simplifying the update process back in your actions.

sample form in editformSuccess.php template:

<?php echo form_tag('editform/updatetitle'); ?>
<?php echo object_input_hidden_tag($newsletter, 'getID') ;?>
Title: <?php echo object_input_tag($newsletter, 'getTitle') ;?>
<?php echo submit_tag('update'); ?>

and in actions.class.php:

<?php
public function executeEditform($request)
{
$this->newsletter = »
NewsletterPeer::retrieveByPk($request->getParameter('id'));
$this->forward404Unless($this->newsletter);
}

public function executeUpdatetitle($request)
{
$nltoupdate = NewsletterPeer::retrieveByPk($request->getParameter('id'));
$this->forward404Unless($nltoupdate );
$nltoupdate->fromArray(»
$this->getRequest()->getParameterHolder()->getAll(),BasePeer::TYPE_FIELDNAME);
$nltoupdate->save();
return $this->redirect(»
'newsletters/view?id='.$request->getParameter('id'));
}

The update code uses the fromArray method to update any properties of your object it holds data for, received from your form. Adding fields to your form doesn’t require changes to the action.

I got into difficulties when it came to setting a boolean field for my object, called “IsPublished”. Wishing to stick with the Object form helpers I investigated the Object_select_tag, however this has a different use altogether – allowing you to grab properties of other objects to match with your current object. The classic example being choosing an author from the authors object to match up to a post object.

I still wanted to save a property for my object, but I didn’t want to have it select from the object, or grab values from other objects. Further searches revealed I wasn’t alone in wondering how to set default selected values and generally get to grips with object_select_tag.

Mixing Object and Form helpers seemed the best solution, using select_tag for my boolean field. However this meant I wasn’t using the Object helper exclusively, so would it still work with fromArray?

The form code generated looked promisingly simple, so I tried a mix of object_input_tag and select_tag in my editformSuccess.php template:

<?php
$defaultOption = »
$newsletter->getIsPublished() == 1?1:0; # get current, set default
echo select_tag('in_published', options_for_select(array(»
0, 1),
$defaultOption));
?>

Note the highlighted property in select_tag. My Object Property is called “IsPublished”. To object-generate a plain text input field I’d have used:

<?php
Published: <?php echo object_input_tag($newsletter, 'getIsPublished') ;
?>

So my current field value would be retrieved, and the Object helper generates form fields using BasePeer::TYPE_FIELDNAME which in turn is used in my fromArray method to update the Db.

Normally one would use select_tag with internal field names (BasePeer:: TYPE:PHP_NAME) and write more action code to marry them up before a save(), however here I have to add my database field name into my view code.

Tethering your templates to your database schema is a route no-one should go down. So the internal name should be converted to the Db name on-the-fly in your template. The Peer classes have a function for this, and its public. The following call converts your usual internal field name for you, ready to drop into your select_tag:


<?php
$IsPublished_translated = BaseNewsletterPeer::translateFieldName(»'IsPublished',BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME )
?>

You could assign this in your action, but it works just as well in the template:

<?php
echo select_tag(»
'BaseNewsletterPeer::translateFieldName(»
'IsPublished',BasePeer::TYPE_PHPNAME, BasePeer::TYPE_FIELDNAME
',»
options_for_select(array(»
0, 1),
$defaultOption));
?>

A final step would be to migrate this into a function higher up that so as to make templates a little prettier when editing.

Twitter ye not – no more UK Mobile updates

August 14th, 2008
post #123 

Looks like there’ll be no more Twitter mobile updates on the UK number. According to the email this morning the cost of sending Twitter updates to our mobiles has become prohibitive.

I’m not sure if there’s a bad guy in this, or if this just shows how social networking doesn’t have the power to sweep traditional business aside after all. That Twitter didn’t come up with a premium service to address this earlier probably means they’re hoping that user outcry will force some sort of reinstatement, a full or partial climbdown on the part of the operators.

We’ll see, but we’ll probably have to log on to see.

Your history is your business, not ours

July 28th, 2008
post #122 

I like the sound of Cuil- all the goodness of their ex-employer without the digital footprint. Their privacy page reads:

Privacy is a hot topic these days, and we want you to feel totally comfortable using our service, so our privacy policy is very simple: when you search with Cuil, we do not collect any personally identifiable information, period. We have no idea who sends queries: not by name, not by IP address, and not by cookies (more on this later). Your search history is your business, not ours.

Right now though I’m waiting a long time for the first few of the 1,682,519,994 results promised on a search of this blog’s title to appear. The first time I tried it I got a rapid response – saying there were no results. But I’m optimistic that this could be my search engine of choice when things settle down. Their claim to examine the context of search queries in order to refine results is interesting and I wonder what it means in practice.

While a good tactic for a launch I don’t imagine the black homepage with centred box will last, not least when they quickly revert to convention for the results; but the results page layout of boxed up summaries is pleasant and readable – not unlike a good news site.

Now I’m waiting for page 2, and the features, privacy and management pages have all gone missing. I’ll come back tomorrow.

Advances in Computer Security and Forensics Conference

July 22nd, 2008
post #119 

I’m really glad I got the opportunity to attend this event. It’s given my own research and writing a bit of a boost, but its also shown me just how important advances in this field are.

On day one we heard from Merseyside High Tech Crimes (HTC) Unit, about their day to day challenges and how they’re overcome. We also heard from a career digital forensic analyst about recovering data from all makes and models of mobile devices: handhelds, phones and the like, and the ways and means of recovering data from the removable media they commonly use.

On day two there was a practitioner talk from Henrik Kiertzner, about the technology’s propensity to nurture self-selecting constituencies, groups of like minded (though possibly geographically dispersed) individuals with ideologies in accelerated development – and how we’re unlikely to even notice them until they make their move.

We heard from Mark Taylor about scoping corporate forensic investigations, which gave me additional avenues of inquiry for my own research.

The keynote speaker Jim Gamble from the Child Exploitation and Online Protection Centre brought us insights – with wit and wisdom – from a truly difficult field and a call to developers to understand the difference their expertise can make to young individuals. Many of the techniques they use in the kind of cybercrime they combat are traditional. Knowing your enemy being one of them.

I’d assumed this would be a dry and technical conference, so its surprising how far social concerns pervaded the discussion sessions and the conference as a whole.