James Morris - JMOZ

Webmaster in '97.

How to Find Out Your Ubuntu Version

| Comments

To find out your Ubuntu version (or codename) use the lsb_release command which will “print distribution-specific information”:

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 11.04
Release:        11.04
Codename:       natty

Or if you just want the string of the codename:

$ lsb_release -s -c
natty

Symfony2 Warning: Session_start(): The Session Id Is Too Long or Contains Illegal Characters…

| Comments

Whilst trying to set up a new test environment I’ve run into another lovely Symfony2 bug/error. I have a functional test with a body as such:

public function testFoo()
{
    $client = self::createClient();
    $client->request('GET', '/foo/');
    $this->assertEquals( 403, $client->getResponse()->getStatusCode() );
}

FYI I’m trying to test access roles are working correctly so I should get a 403 forbidden.

And my relevant config_test.yml:

imports:
    - { resource: config_dev.yml }
    - { resource: parameters_test.ini }

framework:
    router:   { resource: "%kernel.root_dir%/config/routing_test.yml" }
    test:     ~

Upon running this test I get the lovely error:

Warning: session_start(): The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in /home/james/code/bonsai/admin/vendor/symfony/src/Symfony/Component/HttpFoundation/SessionStorage/NativeSessionStorage.php line 87 (500 Internal Server Error)

After messing with the config and looking around, turns out this is a known issue. For whatever reason, my config was missing some required session parameters for testing. Have a look at this issue for more info. To fix it, I had to change the session storage method params in config_test.yml from native (inherited) to filesystem:

framework:
    router:   { resource: "%kernel.root_dir%/config/routing_test.yml" }
    test:     ~
    session:
      storage_id: session.storage.filesystem

Now, the exception is gone and the test runs:

 $ phpunit --stop-on-error --stop-on-failure -c app src/Foo/Bundle/SecurityBundle/
PHPUnit 3.5.5 by Sebastian Bergmann.

..F

Time: 1 second, Memory: 29.75Mb

There was 1 failure:

1) Foo\Bundle\FooBundle\Tests\Functional\SecurityTest::testFoo
Failed asserting that <integer:302> matches expected <integer:403>.

/home/james/code/Foo/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php:59

FAILURES!
Tests: 3, Assertions: 4, Failures: 1.

Now on to the next problem…

Symfony2 FOSUserBundle Roles - a Simple Solution

| Comments

Out of the box, FOSUserBundle does NOT support Doctrine ORM database persisted Roles. The base class they give you to extend has functionality for roles, i.e. setting, getting and checking them, but you will need to write your own code to persist to the database and thus fully equipping the User with role functionality.

The quickest and easiest way to get roles up and running is to use the existing FOS functionality and create your user a new roles field, mapping it as an array type in Doctrine. This is quicker and easier to work with than using separate Role objects. So your user class will need to specify the $roles class member with the following mapping metadata:

/**
 * @ORM\Column(type="array", name="roles")
 */
 protected $roles;

This will tell doctrine to map a PHP array to a SQL CLOB using serialize() and unserialize(). Take a look at the Doctrine mapping documentation.

Schema changes

So now the model has been sorted, the new column needs to be added to the database. Generate a migration for the changes to the users table:

$ php app/console doctrine:migrations:diff
Generated new migration class to "/home/james/fooapp/DoctrineMigrations/Version20111121145741.php" from schema differences.

This will generate said file which will contain a call to a method to add the new column:

$this->addSql("ALTER TABLE users ADD roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)'");

If you want to set up default roles for existing users, under the call to addSql() insert the following line:

$this->addSql(sprintf("UPDATE users SET roles = '%s'", 'a:1:{i:0;s:8:"ROLE_FOO";}'));

Then execute:

$ php app/console doctrine:migrations:migrate
...
Migrating up to 20111121145921 from 0

  ++ migrating 20111121145921

     -> ALTER TABLE users ADD roles LONGTEXT NOT NULL COMMENT '(DC2Type:array)'
     -> UPDATE users SET roles = 'a:1:{i:0;s:8:"ROLE_FOO";}'

  ++ migrated (0.69s)

  ------------------------

  ++ finished in 0.69
  ++ 1 migrations executed
  ++ 2 sql queries

More information on migrations can be found at symfony and github.

This will add the new column to your users table. You now need to create a new user which will save a serialized empty array in the roles column. From here you can add new roles to that user or you may need to sort out existing users which will have nothing in their roles field unless you followed the step above. Trying to update or work with existing users with empty roles fields will most likely give you a Doctrine ConversionException:

[Doctrine\DBAL\Types\ConversionException]                   
Could not convert database value "" to Doctrine Type array

So I suggest setting up a new user with default roles for your system then copying the content of that user’s roles field into existing user’s roles fields.

To test the roles functionality try the following:

$ php app/console fos:user:create jamestest james@foo.co.uk mypassword
Created user jamestest
$ php app/console fos:user:promote jamestest --super
User "jamestest" has been promoted as a super administrator.

If you now check your db, the roles field for jamestest should look similar to:

a:2:{i:0;s:8:"ROLE_FOO";i:1;s:16:"ROLE_SUPER_ADMIN";}

Your User should now be set up to persist it’s roles to the database. You should be able to edit the security.yml file and restrict access to certain parts of your site by url pattern:

access_control:
  - { path: ^/admin, roles: ROLE_FOO }

For further information see symfony security.

A Symfony2 Console Command and the Foursquare API Venuehistory

| Comments

I’ve been playing with the Foursquare API recently, I’m attempting to get a new homepage built and want to display a map of where I hang out. I use Foursquare quite a bit so wanted to get the locations from their API then plot them on Google maps.

There’s a venuehistory endpoint that gives you a massive list of all the venues you’ve checked into with details such as the venue name, location including lat and lng coordinates, and the count of times you’ve checked in.

Here’s a screenshot of their json response.

I want to pull this into my own database so I have a local copy of it and can play around with it. I’m using Symfony2 so I’ve created a console command which I can run on a cron, or on demand. I decided to do it this way as mainly a learning exercise and also this is a bit better than a standard php script.

The command hits the endpoint with my Oauth access token (outside of the scope of this article, but see the docs for details) and then simply loops over the response and creates a load of Checkin entities which the entity manager then persists.

The command takes an optional argument for the access_token or otherwise defaults to a parameter. There’s also an optional flag to disable the truncation of the checkins table. You can see how to set these up along with the help text in the configure() method. Output is handled by the call to `$output->writeln()“ and you can see how highlighting works in the screenshot of the output.

I may write a future post showing how to push the Foursquare code into a service based implementation so look out.

Nginx 301 to External Url

| Comments

I’m currently migrating my posterous blog domain name vietnameseinshoreditch.co.uk to something which I think is a little better and more SEO friendly, shoreditchvietnamese.co.uk. To redirect the existing urls on the old domain to the new domain I need to set up an Nginx 301 redirect.

Currently my DNS A records for vietnameseinshoreditch.co.uk point to posterous’ IP. I want to point them to my own server which is running Nginx and get Nginx to 301 any requests to my new domain (which will point to posterous). This way any previous links lying around will still work and I’ll maintain all of Google’s link juice and eventually shoreditchvietnamese.co.uk will be seen as the canonical url.

Here’s the Nginx config:

Simple. This 301s all requests to the new domain name and maintains the full request uri.

Give it a go, the link below should get 301’d from vietnameseinshoreditch.co.uk to shoreditchvietnamese.co.uk.

http://vietnameseinshoreditch.co.uk/welcome-to-vietnamese-in-shoreditch

How to Strip Exif Data Using Imagick

| Comments

Today I spent a good amount of time trying to figure out how to strip exif data from an image using Imagick. The first port of call was the (pathetic) documentation at php.net. I searched for ‘exif’ but found nothing. Google isn’t too helpful either. There’s a method Imagick::setImageProperty() but that didn’t seem to save the data correctly. There’s also an exif extension but it only reads the exif data, not writes it.

I was tipped off by a colleague to the method Imagick::stripImage() which apparently did what I wanted. The only mention of exif is in a rather helpful comment at the bottom of the page.

To remove the exif data you need to call Imagick::stripImage() on the populated Imagick object and then call Imagick::writeImage() to save your changes. I’ve written a test script below that uses a sample image with exif data from the exif website.

Here’s the script:

And here’s the output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
moz on mz-904 in ~ 
 $ php imagick.php
Array
(   
    [exif:ApertureValue] => 262144/65536
    [exif:ColorSpace] => 1
    [exif:ComponentsConfiguration] => 1, 2, 3, 0
    [exif:CompressedBitsPerPixel] => 3/1
    [exif:Compression] => 6
    [exif:DateTime] => 2001:06:09 15:17:32
    [exif:DateTimeDigitized] => 2001:06:09 15:17:32
    [exif:DateTimeOriginal] => 2001:06:09 15:17:32
    [exif:ExifImageLength] => 480
    [exif:ExifImageWidth] => 640
    [exif:ExifOffset] => 184
    [exif:ExifVersion] => 48, 50, 49, 48
    [exif:ExposureBiasValue] => 0/3
    [exif:ExposureTime] => 1/350
    [exif:FileSource] => 3
    [exif:Flash] => 0
    [exif:FlashPixVersion] => 48, 49, 48, 48
    [exif:FNumber] => 40/10
    [exif:FocalLength] => 346/32
    [exif:FocalPlaneResolutionUnit] => 2
    [exif:FocalPlaneXResolution] => 640000/206
    [exif:FocalPlaneYResolution] => 480000/155
    [exif:InteroperabilityIndex] => R98
    [exif:InteroperabilityOffset] => 1088
    [exif:InteroperabilityVersion] => 48, 49, 48, 48
    [exif:JPEGInterchangeFormat] => 1524
    [exif:JPEGInterchangeFormatLength] => 5342
    [exif:Make] => Canon
    [exif:MakerNote] => 10, 0, 1, 0, 3, 0, 19, 0, 0, 0, 120, 3, 0, 0, 2, 0, 3, 0, 4, 0, 0, 0, 158, 3, 0, 0, 3, 0, 3, 0, 4, 0, 0, 0, 166, 3, 0, 0, 4, 0, 3, 0, 15, 0, 0, 0, 174, 3, 0, 0, 0, 0, 3, 0, 6, 0, 0, 0, 204, 3, 0, 0, 6, 0, 2, 0, 32, 0, 0, 0, 216, 3, 0, 0, 7, 0, 2, 0, 24, 0, 0, 0, 248, 3, 0, 0, 8, 0, 4, 0, 1, 0, 0, 0, 243, 105, 15, 0, 9, 0, 2, 0, 32, 0, 0, 0, 16, 4, 0, 0, 16, 0, 4, 0, 1, 0, 0, 0, 0, 0, 4, 6, 0, 0, 0, 0, 38, 0, 2, 0, 0, 0, 3, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2, 0, 90, 1, 211, 0, 158, 0, 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 140, 0, 2, 1, 128, 0, 14, 1, 0, 0, 0, 0, 0, 0, 1, 0, 4, 0, 0, 0, 0, 0, 0, 0, 2, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73, 77, 71, 58, 74, 80, 69, 71, 32, 102, 105, 108, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 70, 105, 114, 109, 119, 97, 114, 101, 32, 86, 101, 114, 115, 105, 111, 110, 32, 49, 46, 48, 0, 0, 0, 0, 84, 111, 109, 32, 82, 111, 119, 97, 110, 32, 97, 110, 100, 32, 83, 97, 114, 97, 104, 32, 67, 108, 105, 102, 116, 111, 110, 0, 0, 0, 0, 0
    [exif:MaxApertureValue] => 194698/65536
    [exif:MeteringMode] => 2
    [exif:Model] => Canon DIGITAL IXUS
    [exif:Orientation] => 1
    [exif:RelatedImageLength] => 640
    [exif:RelatedImageWidth] => 480
    [exif:ResolutionUnit] => 2
    [exif:SensingMethod] => 2
    [exif:ShutterSpeedValue] => 553859/65536
    [exif:SubjectDistance] => 3750/1000
    [exif:UserComment] => 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
    [exif:XResolution] => 180/1
    [exif:YCbCrPositioning] => 1
    [exif:YResolution] => 180/1
)
*** stripImage()
Array
(
)

Virgin Media - a Long Tale of Super Hub Trouble

| Comments

DISCLAIMER: I now (March 2013) work for Virgin Media as a contract PHP Developer. The views below are on Virgin’s Superhub service and do not reflect my views on the project I am working on (which is a great project) or any of Virgin’s development.

Update 9

Wellsy rang again in the morning as it’s been intermittent again. Apparently if we log a complaint 7 days in a row then the contract is viable to be cancelled.

Found out that their big internal expansion project in this area that should allegedly fix the issues is on the 6th of March 2013.

Update 8 (Tuesday 20th November, 16:15)

Intermittent again so using the iPhone’s 3g. Just found out our neighbour had Virgin also but sacked them off for Sky because of the problems.

Update 7 (Thursday 15th November, 14:20)

Gone down again, been down since 2pm. Both Wellsy and I are working from home today. He’s on the phone to them again with the usual:

“Just look at our account for how much it goes down. This is unacceptable.”

After a lengthy phone call of at least 25 minutes where he had to elevate to speak to someone more useful, here’s what we’ve got:

  • Techy guy fobbed us off to customer services saying the issue would not be resolved till mid Nov.
  • CS had no access to tech data so did not understand why tech guy forwarded to them.
  • CS forwarded to tech guys at Swansea who were “furious” because the initial tech guy was referring to an issue we logged 3 months ago and was still not resolved.
  • This guy said we have 2 options; get rid of Virgin, or reduce 60Mb to 30Mb to pay less (!!??! this was purely to reduce the cost, dropping down does nothing for the service). Contractually we may be able to get out of it, but in the T&Cs area outages are not included, it needs to be bad service to the household - in our case it’s the area that’s the problem.
  • They have an internal planning project to increase the service in the area to meet the demand (so it’s a known problem).
  • Over-demand in the area which they are doing nothing about till next year.
  • Said they could try to credit our account per month, but in reality we know we will get just a few quid for this, which isn’t worth it - our issue is the shitty service.
  • They have an SLA but they also have Ts and Cs which cover the SLA. Area outages or force of nature are not included. Force of nature obviously makes sense but an area outage, for example what we are experiencing, is down to them and their over subscribing of the area!? What is covered is outages to a single household over periods of time i.e. more that 3 outages in a month.

Ok so the chap on the phone has confirmed that the problem is over-demand in our area and not specifically our household. This means that Virgin are knowingly over-subscribing a sub standard service.

As far as I can see, we’ll get bugger all from them, so we now need to decide whether to just leave the service in the hope it will improve at the start of the year, or move to another provider. Personally I want to escalate this to someone further up and get their opinion on our service and what they can do. It’s just so unacceptable it’s unbelievable.

The service has been down intermittently now for 2 1/2 hours, ongoing. Wellsy who works for SAP has had to go to our mates office for the internet, whereas I’ve taken a break from some Django hacking and am now resorting to my trusty iPhone’s 3g.

Update 6 (Friday 26th October, 13:00)

The internet has been fine for a while (although I have been away for a month) but we spotted a Virgin van outside the other day. Since they came, it’s been dropping out continually throughout the day. I’ve noticed it whilst I’ve been developing a script that makes HTTP requests and which constantly keeps throwing HTTP connection exceptions. Occasionally you’ll notice it in the browser where I’ll get the bland grey Google Chrome error page, but then on the next request everything will be working.

Looks like another phone call is in order.

“You know you sent the guys round the other day to fix the internet?”

“Yes, sir.”

“Well, they broke it.”

Update 5 (Monday 20th August, 12:35)

Internet just dropped out again. No DNS, can’t reach anything outside of the router.

Update 4 (Wednesday 1st August, 14:35)

So since the last update it’s gone down a few times more. An engineer just turned up and fitted us some cabling in and around the box at the front of the house.

CABLE GUY

So after talking to him about the situation he tells me there’s a network problem in the area they think, around N1, apparently NW is even worse. Sounds like they’re trying to replace cables and fix things locally to sort it all out.

Ironically Wellsy has just come downstairs moaning that now he’s replaced the cables it’s all gone a bit slow.

Update 3 (Wednesday 11th July, 22:17)

At around 20:00 tonight Virgin media superhub went down AGAIN. My housemate rang the usual number which he said took about 6 minutes to speak to someone, and then it trolled him through a load of menus and kept cutting out during the password questions:

“Please enter the CRRRRFFPPPFFCCRRRR letter of your password..”

He got to some sort of badly pronounced automated notice saying that there was errors in the “E8” or “A8” area.

It’s just after 10pm now and the modem has started working again.

Update 2 (Tuesday 10th July, 16:55)

The engineer is here now fitting the new Tivo so at least they came through with that, he’s a decent guy, I’ve been talking to him about the service and he says he’s heard of problems in the Dalston area and that they should be able to find out what is wrong and fix it rather than sending us around in circles.

Here he is installing the Tivo.

Virgin Media engineer

Oh god it’s crashed already…

Virgin Media Tivo

Just before he left, the engineer suggested we remove the filter on the superhub modem which was fitted some time ago to try and fix the power issues. We’re gonna try this and see how it goes (shouldn’t the engineer be doing this rather than us dismantling the modem?)

Update 1 (Tuesday 10th July, 13:08)

So I tweeted that virgin were down again in the morning and I’ve just received a reply from @virginmedia which is more than likely a bot that scrapes twitter for ‘virgin media down’.

The ‘smartphone friendly link’ 302s to some pointless page telling me they’re “making some changes”. Great. What changes? How long for? How often are these changes?

Although the service seems to be back up and running I have no idea what happened or really why it happened and I think some twitter guy at Virgin just tried to confuse me by responding with some non contextually specific question. And how am I meant to know if “making some essential changes” which is written on YOUR website is about the website or area. So basically their response on twitter hasn’t helped and instead served to confuse me.

I pointed them to both of my posts about the service hoping they’ll read it. If they don’t maybe I’ll have to create a script that tweets them “virgin media is down” and stick it on a 1 min crontab.

Virgin aren’t great

Y U NO WORK

You can read my original post at VIRGIN MEDIA SUPER HUB A.K.A. HOW VIRGIN MEDIA EFFED MY LIFE to get some context on this.

Virgin Media superhub is down again, Tuesday 10th July 2012 at around 10:00am. I think we’ll sack it off today and go to Haggerston Espresso Room for a coffee and somewhere where the goddamn internet works, or last resort tether my iPhone and use the 3g connection which no doubt will be better than Virgin.

I’ve been meaning to update my original post about Virgin media superhub being rubbish for a long time now, since then the service has REMAINED BAD and we have had constant problems. Engineers have been sent out, they all feed us different stories and presume we know jack all about the internet. The only decent one that came (of about 10) fed us some bullshit about the power band being too wide and then adjusted it but it still didn’t work reliably. Actually he widened it where as the one before him unwidened? squeezed? it.

It went down last week and Wellsy ended up on the phone to them AGAIN; there must be at least 20 calls logged on our account, it’s clear we have a problem yet it’s never resolved and we get sweet fa compensation for it.

They’re back up now as I’m writing this at 10:33am.

So after it going down last week we also found out that the deal we had is now over and the monthly cost has gone up. Obviously we’d had enough of this bullshit and Ryan gave them a ring on the phone and shouted at them for about half an hour with the sole intention of leaving and going to Sky. I can probably get a cheap deal there as I used to work for BSkyB and have a few contacts still at the place - they’re constantly doing deals for family and friends so there’s a very strong case for us to move there. (They’re back down again now at 10:43am) Anyway they ended up offering us some upgrade package - we get Tivo and a larger capacity box, the speeds get upgraded to some alleged monumental amount which we will never achieve and one of the rooms is getting an extra connection and a Tivo box. Oh and I think the price stays roughly the same. So not only do they provide us with a shit service, they abuse and take advantage of our kind hearted nature and blag us to stay with upgrades.

Ironically they’re meant to be installing it today some time and the service is all over the place.

Wellsy has just reminded me to moan about their FUCKING REMOTE! Useless piece of crap busted and started eating the batteries like they were chocolate biscuits; we ended up BUYING A NEW ONE OFF EBAY. You can stick that on top of the shitty service compensation you already owe us that has started from today.

Last point I want to note is that all of this time when we have rang them they’ve tried to push it under the rug telling us there’s no problem and treating us like internet users on the same level as my Dad, e.g. “have you tried turning it on and off again”. Only once did one of the telephone guys admit there might be a problem in the area. So the next day we happen to find a Virgin engineer round the corner with the box open, we spoke to him briefly and he told us that there’s a problem in the area and I’m sure either he or the telephone guy mentioned OVER SUBSCRIPTION to the service, not our goddamn shitty superhub modem wireless router thing, THE PROBLEM IS IN THE SERVICE.

So now I’ve written this I will try and keep it updated with every time they mess up in the hope that some day they will actually provide a reliable service. Right, now I’m off to upload this post USING MY IPHONE’S 3G CONNECTION.

SplObserver, SplSubject - Removing Dependencies With the Observer Pattern

| Comments

I work with symfony every day - I’m a backend developer who mainly enjoys designing and writing domain objects, core services and APIs.  I like to create loosely coupled objects where each object has a clear role and is composed of other objects.  Working on a symfony app, you usually have a mix of domain objects that are used by symfony actions, interspersed with symfony specific code such as logging and sfContext type stuff.  A common bad practice I see is symfony specific code peppered inside of domain objects that could be used elsewhere (such as inside of a Zend app or a script from the cli) but now can’t as they’re coupled to the symfony code.

The Observer pattern

One way you can remove an unwanted dependency is to use the Observer pattern - the dependency is pushed from inside the subject object to the client code that initialises the subject. The subject object exposes events in the code (such as before or after certain method calls) by calling a method notify(), this then notifies all observers that were set up at run time. The subject passes an instance of itself when each observer is notified so that whatever the implementation of the observer, it has full access to the context of when notify() was called. In (somewhat) simple terms, you pull out the line of code that is a dependancy, replace it with a call to notify(), then push the dependant code into an object that implements update() and attach this observer at runtime, we will use the interfaces provided by SPL - the Standard PHP Library, SplSubject and SplObserver.

The Scenario

Right, so I’ve tried to articulate this but as always a code example is best.  The scenario is as follows and is something I’ve seen numerous times: we have a symfony action that hits a web service and for this example just spits out the response.  There are Service classes (which I won’t show an implementation for as they’re simple) which basically contain some business logic, parameters, and endpoint details such as url and HTTP method.  The Client object takes a Service object and transport object (HTTP in this case) puts them both together and sends a HTTP request to the web service endpoint and returns the response.  Inside all of this is the need for logging so there is symfony specific code coupled to the cohesive and loosely coupled Client object. I’m going to show some example code and then refactor it till eventually the dependency is removed and the Observer pattern is implemented.  Obviously there are many ways to do this and many reasons for and against it.  Do not take this as dogma - it’s merely here to demonstrate an option you can take.  And none of this code is tested, just free styled.

The Action

The action simply chucks a Service and Http object into the client for it to use and calls it.

The Client

The ServiceClient takes an instance of a Service and a Http object which are injected at construction.  There’s an accessor and a mutator so the Service can be switched at runtime.  The main code is inside call() which sets up the Http request and returns the response.  You can also see we are logging the Service call details by getting the logger from sfContext - not nice.

Refactoring out sfContext

Nobody likes sfContext calls inside domain objects.  Fact.  So let’s make use of dependency injection and push it to the client code.  Here’s the new action and Client.

That’s better than before but will still have the symfony dependency in the constructor and a call to a method named info(). This could be solved by using an adapter, but who said we wanted any logging inside this class in the first place? Services, Service Clients and Http objects are all fairly cohesive, logging is not.

Implementing the Observer pattern

Shit just got real. We’ll now modify the Client so it implements SplSubject, the interface so kindly provided by PHP’s SPL. We’ll create a new Observer object that implements SplObserver and push the logging to it, then all that’s left is to modify the action code. So first up is the Client.

You can see we are implementing the SplSubject interface where we have to declare 3 methods, attach(), detach() and notify(). As we are a subject we need to maintain an array of Observers, we do this by using a hash of the object as a key to the array which allows us to easily detach() it. notify() is our event where we loop over each Observer calling update() and passing them the current instance so they have full access to the context of when notify() was called.

Next up the Observer.

Here you can see the object has one clear role – to use symfony’s logger and the Subject that we passed in (our Client) to log details about the Service that was called. We could easily create another Observer that uses Zend’s logger or create something that has a function other than logging. The point is we pushed the symfony dependency from inside the Client object into a separate, decoupled object.

And finally the action that brings it all together.

You can see we construct our Client with 2 cohesive objects then attach an Observer directly after. We know that when notify() is called our logger will log details of the Service that was called. We’ve pushed the dependency out of the domain object and up into client code so that the domain object is no longer coupled to symfony, we could use it with Zend if we really wanted to (but probably don’t). As mentioned before, we could attach multiple Observers each with slightly different functionality. All we know is that each Observer wants to do something at the point that notify() was called. Nuff said.

Virgin Media Super Hub a.k.a. How Virgin Media Effed My Life

| Comments

DISCLAIMER: I now (March 2013) work for Virgin Media as a contract PHP Developer. The views below are on Virgin’s Superhub service and do not reflect my views on the project I am working on (which is a great project) or any of Virgin’s development.

UPDATE: The most recent (July 2012) and updated post about our Virgin Media problems is here.

Ok, so at home we have Virgin Media Super Hub with the 50Mb package. To cut a long story short, it’s shit. The following is a complaint from my housemate that he’s sent to the top people at Virgin as we’ve had it to our wits’ end with them. I’m sticking it here for visibility and the hope that someone else can empathize with us.

FYI. I’m not the typical complaining customer - I’ve been with Virgin since they were Blueyonder (and whatever before that) and the service was great, but the new service for the 50Mb Super Hub is the worst service I’ve ever had. Ever. We switched from Sky to Virgin on the promise it would be a great, fast service which it is not. We never had any problems with Sky and I’m thinking of switching back - I can get a discount as well seeing as I work there :)

Dear Mr Berkett,

Firstly, I hope this is the correct email address to contact yourself.

Secondly, I apologise for being one of those annoying customers who tries to bypass the usual complaints system and “go to the top” however after the 55 minute phone call I just had with your customer services team, I really don’t know what else to do.

To give you a brief history of our account:

We signed up for 50mb broadband in September 2010. The installation process was long & tedious. The engineers didn’t have any routers with them, so we had to buy our own as getting one delivered was going to take so long. We then had constant issues getting the virgin modem to connect correctly with the router we had bought, so we rung to complain and they mentioned we could have an all in one superhub which would rectify this issue. Happily we agreed and awaited arrival. Some weeks passed and no hub arrived. We called again to be told there was no record of an order for a superhub being made, and that the superhub wasn’t even available for 50mb customers yet. They apologised for giving incorrect information and told us that as soon the superhub was available we’d be sent one free of charge.

More weeks of bad connection, speed and intermittent issues passed. No superhub arrived. We called again to be told that we weren’t entitled to a free 50mb superhub so we would have to pay about £75 for it. Disgusted that we were being messed around again I spoke to a manager, explained all of our issues and if memory recalls correctly we eventually received a 50mb superhub for free.

This is where the real problems began. The engineer who was supposed to personally bring our superhuib and install it (according to the customer services team) had gone AWOL. So they would need to send another engineer out with another hub. When he arrived, he installed the hub and told us that we needed to fill in a registration page online. He left and we filled in the form. At the last page, the internet connection died and we never knew if the information we had just entered had been saved. We couldn’t seem to access the page again either. The internet came back on but was riddled with issues. Our speed test results were around 2mb (nowhere near the 50mb we were paying for) the line test was giving us an F grade, with over 80% packet loss and a huge jitter score.

We called many times to complain, always receiving different excuses, usually related to “power levels being too high” and sometime too low! We did a lot of online research and found an untold amount of virgin media customers had similar issues with the superhub.

Quoted from http://www.digitalspy.co.uk/forums/showthread.php?t=1449681 “If you check out the Virgin Media broadband forums you’ll find the Superhub is plagued with problems and complaints from Superhub users. Virgin Media are fully aware that their Superhub has issues and have been promising a firmware upgrade for some time, but it has not happend yet. ETA for the Superhub firmware upgrade is reported to be May 2011”

As advised by many forums and eventually Virgin Media customer care, we switched off some of the router services such as IP Flood detection and the firewall. This drastically improved the line test score from an F to an A. We thought this had finally solved our problems.

Unfortunately, the service continued to drop out, usually when streaming media, or using FTP connections, it seemed to just not be able to handle any constant streams of data. We called many, many times to complain over the following few months, we’ve had 4 engineers out, some said they lowered the power levels, one added a filter to the line which would help. The last engineer told us there was something wrong with the line, but he couldn’t tell what. He advised us to find another broadband provider.

Completely disheartened by his comments, we called again to complain, we were promised a call back. No call back came. Then began the billing issues. The email address you had on file was incorrect, so we never received any bills. One of the direct debits had failed because it was unusually high, so we were hit with late payment fees, and disconnected immediately. No letters were sent, no communication whatsoever, assuming it was the usual technical issues we called the tech team, they advised us it was a billing issue so I was passed through to them. They explained we had missed a payment (which i was at the time, oblivious to) I made the payment and waited 24 hours for the broadband to come back on. It did not.

I rang Virgin again having to use my mobile because you had cut our landline off now too. I complained again, and our internet was restored immediately. About 4 days after this saga we received 3 letters (dated the day before) stating we had missed a payment, and that within 5 days we would be cut off. How useful is that? I rang to complain again that sending these letters a week late is useless to us, they blamed the postal service, I stated that the letters were dated the day before the call, and they apologised.

Back to our usual poor connection, dropping out at many points throughout the day. Another 3 weeks passed and we were cut off again. Similar issues, no bill was received, late payment fee added, then removed. I rang up and paid, internet restored. At this time I explained how unhappy we were to be paying £80 a month and receiving such a terrible service from day one. A very helpful woman (for once) from customer services said she would arrange an engineer, I said we’d already had 4 too many and she seemed shocked that it still wasn’t resolved. She did a line test and agreed there was a problem. She said she would escalate it to the highest level of complaints and investigation to get this sorted once and for all, then look at compensation.

A week passed and no call back was received, then we were cut off AGAIN. This is today, I call and am told that £10 is still outstanding, I ask what it’s for and they advise that when the last customer service representative took off the last late payment fee, they wrongly charged us £10 less, when in fact the £10 credit was added to next month’s bill, so £10 was left on the account unpaid. We had received no letters or warning as usual, just cut off out of the blue. (I’m fairly sure this isn’t policy at all, you’re supposed to warn customers before cutting them off) Angered by yet another out of the blue disconnection, I asked to be put through to cancellation to close the account. I was told I couldn’t do that until I paid £10. I was also advised that there would be a £180 cancellation fee. I argued that we were expecting a call regarding the poor service and compensation, I was then put through to a “manager”, Carl. This guy was the final straw. Comparing the service to a ‘Rolls Royce’ because it’s so good, he argued that we had clearly had a great service due to our high download usage. I advised him that’s because I work from home a lot, and there are 5 of us living here. He then suggested that was the problem, that too many machines were draining the bandwidth. I advised that was a silly comment, and something that we had clearly addressed months back, long before we had 4 engineers, and escalated complaints etc.

He then suggested that sometimes kitchen appliances can cause problems. I asked if he was in the technical team, he admitted he was not. So we ended that conversation. He then quite rudely, stated that the only way we would have our connection restored was if we paid £10. I said out of principal alone, I’m not paying any more money. He said “well then you won’t have our great service” he kept dropping comments like this at me, and that we download too much anyway. I advised its an unlimited service, so we’re well within our rights to download a lot of content. He agreed and stated that no other provider offers that so it’s not like we can go elsewhere. I advised that BT offer unlimited 40Mb broadband. He argued that they only provide 24 megabyte speeds, and virgin offers 50megabytes. I advised Virgin do NOT offer 50Megabytes. They offer 50Megabits. I asked him to learn the difference between bits and bytes if he’s going to lecture me on what I am and am not entitled to spend my money on. He then returned to his usual script of “You have to pay £10” I asked to speak to his manager, he said that would take up to 24 hours. I asked to speak to one immediately,. He said no. I asked to speak to one of his colleagues now, he said no. Eventually, I paid the £10. I asked him to log the complaint on the system with all of the other complaints. That phon ecall took 55 minutes. And now I’m emailing you hoping that something will happen.

We’re not asking for much, just one or possibly if you can stretch to it, 2 of the following:

1) Some form of cash compensation 2) You stop cutting us off 3) you fix our broadband line issues

One would hope, that those 3 are the basics that you could expect from a £45 a month broadband service.

P.S - Yesterday, our TV remote packed up too. We replaced the batteries but it’s still dead. If I didn’t laugh about this, I’d cry.

Shoreditch PHP?

| Comments

If you’ve got a decent PHP contract in the Shoreditch area, hook a brother up. I want to ride my fixie bike to work.