Behat and Symfony2 - A Simple Gotcha

Recently we were using Behat on a new project with the Symfony2 extension. It took a bit to get it up and running correctly as the docs (for the extension setup) seem to be incorrect. First place the behat.yml directly in the project root. Second, when using the “@” notation to reference your bundle you need to be sure to enclose it in quotes. For example, ‘bin/behat –init “@MyBundle”’. Without the quotes it will not be parsed correctly and will not setup the structure as you want.

If you are running into the following error:

  [RuntimeException]                                                         
  Context class not found.                                                   
  Maybe you have provided a wrong or no `bootstrap` path in your behat.yml:  
  http://docs.behat.org/guides/7.config.html#paths     

Most likely the initial setup didn’t go correctly. We kept having that issue whenever we added the behat.yml to our root directory, but then didn’t use the quotes to enclose the @MyBundle. Hopefully this saves you the headache!

I’ve shot over a pull request to the main behat repo for the extension so it hopefully will be fixed soon:

Happy testing!

Custom Templates with jQuery File Upload

Recently I was working on a project which was using the jQuery File Upload Plugin to do multiple file uploads. I needed to show the progress of each upload (in this case just images). Looking through their documentation it shows how to a few ways to do custom templates. By default it uses the Javascript Templates Engine for all of its templating. I wanted to use just a div on the page for my template. Here’s how I ended up doing it.

First My basic markup for the html:

<input type="file" id="fileUploads" name="file" multiple />
<div id="uploadContainer">
 <div class="uploadedImage">
  <img src="myimg.png">
 </div>
 <span id="newImages"></span>
</div>

<div id="template">
 <div class="uploadedImage">
  <img src="" />
  <div class="progressbar"><span class="bar"></span></div>
 </div>
</div>

Basically my “#template” div was a hidden div on the page which I used as the photo being uploaded. Now for the javascript:

var progressElements = { };

$(document).ready( function(){
	
    $("#fileUploads").fileupload({
      dataType: 'json',
      done: function(e, data){
    	    
          var fileName = data.files[0].name;          
          var el = progressElements[ data.files[0].name ];        
          el.find("img:first").attr("src", data.result.thumbnail);
          el.find(".progressbar").hide();
      },
      progress: function(e, data){
    	    var el = progressElements[ data.files[0].name ];
    	    var progress = parseInt(data.loaded / data.total * 100, 10);
    	    el.find(".bar").css('width',progress+"%" );
      },
      add: function(e, data){

   	  var template = $("#reviewTemplate").html();    	       	 
    	  $("#newImages").before(template);

    	  progressElements[ data.files[0].name ] = $("#uploadContainer .uploadedImage:last");
    	  
    	  $("#fileUploads").fileupload("send", {files: data.files});
      },
      autoUpload: true,
      url: 'myUploadUrl',
    });

});

It ended up being pretty simple and self explanatory. The ‘progress’ function is called each time there is a progress update. You can do more advanced templates using their templating engine, however as I was adapting the code to an existing layout and was on a time constraint this was the route I took.

Hope this saves you sometime if you are looking to just quickly add a progress template for the uploaded images.

Gmail Reporting Tons of Used Space? This may help!

Recently I had to upgrade my Gmail account for additional storage. I was nearing the 8 free gigs of data they give you and didn’t want to keep seeing the big red “Buy more storage!”. I bought the $5/year 20 gig plan. A few weeks later I noticed that my Gmail was now reporting i was already using ~18 gigs of my total 30 gigs of data. I couldn’t believe it, how did I manage to more than double my used Gmail space within 2 weeks? I had used Gmail for 8 years to get to 7 gigs of data.

After looking around there didn’t seem to be anyone who could report the problem, nevertheless have a fix. I then tried to empty my Trash, which at the time said ~200 messages. As soon as I emptied it my used space dropped to 7.3 gigs, which is what I expected.

Long story short, it would appear that Gmail has a bug in reporting the number of actual messages in the trash, or doesn’t truly ‘empty’ it unless click it. If you think you are using much less space than it is reporting, try emptying your trash manually. It worked for me and a number of other guys in the company.

MetaForce: A MetaTrader4 Integration, Opening MT4 to the Web

We know we’ve been silent here lately, however we are happy to announce our full revamp of one of our products: MetaForce. MetaForce is a product we’ve had around for a while and have several clients using.

What is MetaForce? MetaForce allows MetaTrader4 data to be extracted to numerous CRMs, support systems, and custom client areas. With MetaForce brokers can do things they never have been able, a few highlights are:

  • Process deposits automatically to MT4 via their payment processors
  • Manage MT4 accounts from their CRM, support system, or client area
  • Allow clients to reset their MT4 passwords from the web

There are two levels of MetaForce. One which syncs data from the MT4 platform into a CRM, support system, or client area. The second which does the data sync, but also allows interactions back from the CRM, support system, or client area into the MT4, such as creating accounts, deposits, etc.

MetaForce is the first product of its kind. No longer are brokers required to use the MT4 programs to manually process account applications, deposits, and other business processes; brokers can now use their own platforms to do these actions. With MetaForce brokers can streamline their processes and cut down on training time.

For more information on solutions please visit the http://getmetaforce.com">product's site.

Symfony2 - Getting All Errors From a Form in a Controller

Recently I was working on an API call which uses a form to validate the data you are passing in. I ran into the issue of getting all the errors for a form in Symfony2 is not as straight forward as you would think. At first I tried $form-&gt;getErrors() and then looped through the errors. That didn’t get all of them. After looking around I found:

<?php
    public function getAllErrors($children, $template = true) {
    	$this->getAllFormErrors($children);
    	return $this->allErrors;
    }
   
    
    private function getAllFormErrors($children, $template = true) {
    	foreach ($children as $child) {
    		if ($child->hasErrors()) {
    			$vars = $child->createView()->getVars();
    			$errors = $child->getErrors();
    			foreach ($errors as $error) {
    				$this->allErrors[$vars["name"]][] = $this->convertFormErrorObjToString($error);
    			}
    		}
    
    		if ($child->hasChildren()) {
    			$this->getAllErrors($child);
    		}
    	}
    }
    

    
    private function convertFormErrorObjToString($error) {
    	$errorMessageTemplate = $error->getMessageTemplate();
    	foreach ($error->getMessageParameters() as $key => $value) {
    		$errorMessageTemplate = str_replace($key, $value, $errorMessageTemplate);
    	}
    	return $errorMessageTemplate;
    }

This works really well for any errors which are bound to a field. However it will not catch global errors such as a unique validator. It should probably be renamed from getAllErrors(). In order to get those you need to also loop through $form->getErrors(). This was returning the global errors only for me. Here is my code in the end:

<?php
        foreach($form->getErrors() as $e)
            $errors[]=$translator->trans($this->convertFormErrorObjToString($e), array(), 'validators');
        
        
        foreach($this->getAllErrors($children) as $key=>$error)
            $errors[]=$key.': '.$translator->trans($error[0], array(), 'validators');

There may be a better way, just wanted to shoot this out as not many people had good solutions on it.

Bonus: If you are using the translator service on validators and you get an error which is the ‘validators’ translation files, make sure you use the proper domain, ie: $translator->trans(‘key’,array(),‘validators’).