Eclipse: Adding File Associations

We regularly write PHP, using the CakePHP framework, in Eclipse (Juno, with PHP Development Tools (PDT)). The view template files in CakePHP have the .ctp extension, which Eclipse does not, by default, recognise as PHP files, so you do not benefit from any of the helpful Eclipse PHP tools. However, you can add an association (i.e. tell Eclipse that .ctp files are PHP files), as follows:

  1. Go to Window > Preferences to open the Preferences box
  2. Go to General > Content Types in the menu
  3. In the Content types box, expand Text and select “PHP Content Type”
  4. Click “Add”
  5. Type “.ctp” in the box that appears and click OK
  6. Click OK to close the Preferences box

Note that you will have to close and then reopen any .ctp files that are already open in order for them to be recognised as PHP files.

Eclipse: Changing Project Type

I’ve just added a new project from an existing location in Eclipse Juno, and for some reason it wouldn’t let me create it as a PHP project. Instead, I had to just create it as a general project. Having done this, it is fairly easy to convert it to a PHP Project, by doing the following:

  1. Open the .project file for the new (non-PHP) project in a text editor
  2. Open a .project file for an existing PHP project (or, if you haven’t got an existing PHP project, create one in your workspace and use the .project file from that)
  3. Copy the <buildSpec> and <natures> sections from the PHP .project file (from 2. above) to the .project file for the project that you want to change to a PHP project (from 1. above)
  4. Save the new modified .project file and refresh the workspace
  5. The general project should now be a PHP project

The .project file for my PHP projects looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
   <name>project_name</name>
   <comment></comment>
   <projects>
   </projects>
   <buildSpec>
      <buildCommand>
         <name>org.eclipse.wst.validation.validationbuilder</name>
         <arguments>
         </arguments>
      </buildCommand>
      <buildCommand>
         <name>org.eclipse.dltk.core.scriptbuilder</name>
         <arguments>
         </arguments>
      </buildCommand>
   </buildSpec>
   <natures>
      <nature>org.eclipse.php.core.PHPNature</nature>
   </natures>
</projectDescription>

Magnolia CMS: Getting node/page/paragraph IDs and user details using JSP

Just a quick note to remind me, and let anyone else who tries to do this know, how to access the unique id (uuid) of a page or paragraph, and details about the current user in a JSP page in Magnolia CMS. We are watching to save, via AJAX, information about how students use pages and paragraphs (in particular self-test question paragraphs) within our Magnolia installation, and need these details in order to do this.

Displaying the node/page/paragraph ID

If you put this code in a page template, it will show you the unique ID for the page. If you put it in a paragraph template it will show you the unique id for that paragraph. These IDs do not change when you move a page, or a paragraph within a page.

<cms:out nodeDataName="uuid" var="uuid" />
<p>${uuid}</p>

Displaying the name of the current user

<jsp:scriptlet>
   String user = (info.magnolia.context.MgnlContext.getUser().getName()).toString();
   out.println("&lt;p&gt;" + user + "&lt;/p&gt;");
</jsp:scriptlet>

Creating a JAR file

I’m no Java programmer, but we used Magnolia CMS, a Java-based content management system, for creating interactive online learning materials, so have to mess about in the world of Java from time to time. In order to make modifications to the modules that we use for Magnolia (generally minor bug fixes or alterations to make them better suited to our needs), we have to unpack, edit and then repack .jar (Java ARchive) files. I always forget how to repack the jar files, and have recently had to set up a new PC to do it, so here’s the process I used, in case it is useful to anyone (especially the future me):

  • Get and install the latest Java Development Kit: http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
  • Add the location of the JDK bin (where jar.exe lives) to the Windows Path environment variable (Windows 8, but similar for other Windows versions):
    • Go to Control Panel > System > Advanced system settings > Environment Variables…
    • Under System variables, find the Path variable, select it and click Edit
    • Add “;C:\Program Files\Java\jdk1.7.0_21\bin” (or whatever the path to you JDK bin directory is – it will be something like this if you install with the default location settings) at the end of the Path variable
    • This will enable you to run jar.exe by just typing “jar …” in the command line
  • Open a command prompt and navigate to the directory containing the class files etc that you want to “jar”
  • Use this command to create the jar: “jar cf jar_name.jar *”
    • c = create new archive
    • f = specify file name
    • * = add all of the files in the directory to the jar
  • That’s it, you should now have a new jar file called “jar_name.jar”

 

XAMPP (1.8.1) on Windows 8 – Apache not starting as Port 80 “in use by system”

I have recently upgraded to Windows 8 and installed XAMPP 1.8.1. On trying to start Apache using XAMPP Controller, I kept getting an error message saying that Apache could not be started because port 80 (the default port for Apache) was “in use by system”.

After a bit of searching around, one common solution, and the one that worked for me, was to turn off the “World Wide Web Publishing Service”, as follows:

  • Go to Control Panel > Administrative Tools > Services
  • Find “World Wide Web Publishing Service”
  • Right click and select “Stop”
  • Right click and select “Properties”, then change “Startup type” to “Manual”

If this doesn’t fix it, you can find out what is using port 80 as follows:

  • In a Command Prompt, run ‘netstat -ao > netstat.txt’ to write active connections and associated process IDs (PID) to a file (for me, there were too many to just view them in the command prompt)
  • Find the PID that is listening on port 80 (0.0.0.0:80) – for me, the PID was 4, which seems quite common
  • Open Task Manager (Ctrl + Shift + Esc), right click on the column headers, and then click PID to show the PID column. Sort by PID to find the process for the PID that you identified above.

Once you know the process that is causing the problem, a bit of Googling (other search providers are available) should help you fix it.

CakePHP 2.x: Migrate from 1.3

The CakePHP 1.3 to 2.0 migration guide does probably cover most of what we have found below…but it appears to be written by and for the developers of CakePHP rather than for people who use CakePHP to develop their own applications. So here are some of the things we are doing during our 1.3 to 2.4 migration (although I can’t guarantee that they were all actually necessary), in case they help others. Please note that this is a work in progress 🙂

Upgrade Shell

Upgrade Shell – this promised considerably more than it delivered but did at least rename the controllers and changed the case of some of the folders under app. The rest were corrected using the Folder Names section of the migration guide, including the Views sub-folders and renaming ‘helpers’ to ‘Helper’

Files to copy from 2.x code

Copy the following from your download to the same place in \app:

  • \app\webroot\index.php
  • \app\View\Helper\AppHelper.php
  • \app\Config\core.php (contains a new error handling config. info)
  • \app\Config\routes.php (contains a couple of new setting to load plgin routes and ‘default’ CakePHP routes.

Update Paginator code

In view:

echo $this->Paginator->counter(array(
    'format' => __('Page %page% of %pages%, showing %current% courses out of %count% total', true)
    ));

changes to:

echo $this->Paginator->counter(
    'Page {:page} of {:pages}, showing {:current} records out of
     {:count} total'
);

In controller, this syntax:

$this->paginate['Event'] = array(
            'order'=>array(
                ..
                ),
             'conditions'=>array(
                ..
                 )
             );

$this->set('events', $this->paginate());

changes to:

$this->paginate = array(
                'order'=>array(
                     ..
                    ),
                 'conditions'=>array(
                    ..
                     )
                 );
$this->set('events', $this->paginate('Event'));

Change all ‘action’ functions in ctp files from:

function index(){}

to

public function index(){}

Auth Component

Now required to explicitly log users in – not done automagically any more. Where we use WebAuth to authenticate and manually log users in:

if($this->Auth->login($user_id))
     {
     $this->Session->setFlash('Logged in');
     }

becomes:

$this->request->data['User'] = array_merge($this->request->data['User'], array('id' => $user_id));
if($this->Auth->login($this->request->data['User']))
     {
     $this->Session->setFlash('Logged in');
     }

Form2Helper

Although, some of this is specific to the Form2Helper (to make MySQL enum fields show enumerated values rather than a number), some of these points will apply to all helpers:

  1. Change name of helper to Form2Helper.php, instead of Form2.php;
  2. Change App::import(‘Form’) to App::uses(‘FormHelper’, ‘View/Helper’) above class definition (replacement of App::import in 2.x with App::uses)
  3. $this->_introspectModel($modelKey, ‘fields’, $fieldKey) instead of $this->_introspectModel($modelKey) (changes to _introspectModel)
  4. After an hour or two of trying to work out why the first enum input in a form was being output as a standard text box while subsequent inputs for the same field in the db, were coming out correctly as selects, I realised that:
    isset($this->fieldset[$modelKey])

    was not returning false when:

    $this->fieldset[$modelKey]['fields']

    was returning ‘null’ so I have replaced it with:

    if (!isset($this->fieldset[$modelKey]['fields'][$fieldKey]))

    and it’s all working nicely now.

Request Object

Use $this->request->data instead of $this->data

FormHelper

FormHelper::select(string $fieldName, array $options, mixed $selected, array $attributes)

becomes

FormHelper::select(string $fieldName, array $optionsarray $attributes)

and

$html->link

becomes

$this->Html-link()

Selecting and Replacing Columns/Blocks of Text in Eclipse

In Eclipse (I’m using Eclipse June 4.2.2 at the moment), it is possible to select columns/vertical blocks of text by using Alt+Shift+A to switch to block selection mode. You can then drag over a column/block of text. With a block selected, typing text will replace the selected text in all of the selected rows.

CakePHP-Mailchimp-datasource 1.3 Read Method

If anyone’s still using CakePHP v1.3 of this brilliant datasource which allows you to treat data on subscribers in MailChimp as if they were in a local model, I had to make a few changes to make it work with v1.3 of the MailChimp API.

 
function read($model, $queryData = array()) {
 $url = $this->buildUrl('listMemberInfo', $queryData['conditions']['emailaddress']);
 $response = json_decode($this->connection->get($url), true);
 if(isset($response['errors'])&&$response['errors']>0) { //this is how errors are indicated
 return false;
 }
 return $response['data']; //allows find('first') to return $response['data'][0]
 }

WordPress: Improvement to Form Manager plugin when used with Members plugin

As mentioned in my earlier post, the WordPress Form Manager and Member’s plugins integrate fantastically. However, one thing that didn’t quite perfectly was that if a user was allowed to view the submission data for forms (the ‘

This is because, by default, clicking on the name of a form takes you to the edit/design page, whether or not you are allowed to edit the form. Therefore, if you are not allowed to edit the form, it doesn’t show the page, and you see nothing except the tabs for the actions that you are allowed to access, in this case the “Submission Data” tab. To see the submission data, you then have to click on this tab to view the data. Obviously, this second click is annoying, and the blank page is ugly/confusing.

Thankfully, this issue was quite easy to fix, by replacing line 155 of wordpress-form-manager/pages/main.php with the following code:

<strong>
   <?php if(!$fm_MEMBERS_EXISTS || current_user_can('form_manager_forms') || current_user_can('form_manager_data')) { ?>
      <a class="row-title" href="<?php
      //If the user can edit forms, take them to the edit page, as usual
      if(!$fm_MEMBERS_EXISTS || current_user_can('form_manager_forms')) { 
         echo get_admin_url(null, 'admin.php')."?page=fm-edit-form&sec=design&id=".$form['ID'];
      }
      //Otherwise, if the user can view the data, take them to the data page
      else if(current_user_can('form_manager_data')) { 
         echo get_admin_url(null, 'admin.php')."?page=fm-edit-form&sec=data&id=".$form['ID'];
      }
   ?>"><?php echo $form['title'];?></a>
   <?php } 
   //If user has no form permissions, do not create a link
   else { 
      echo $form['title']; 
   }  ?>
</strong>

Basically this just means that:

  • If the Members plugin isn’t installed, the link goes to the edit/design page
  • If the user can edit forms, the link goes to the edit/design page
  • If the user can’t edit forms but can view data, the link goes to the submission data page
  • If the user can’t edit forms or view data (i.e. they can do nothing with individual forms), then the form name isn’t made into a link

I hope this is a robust improvement – it seems to work well for me, and will prevent my ‘view data only’ users from getting annoyed/confused by the form link taking them to the wrong place.

WordPress Form Manager and Members plugins integrate brilliantly

We’ve been working with the WordPress Form Manager plugin for a while, and have found it an excellent and flexible way to create forms in WordPress (thanks Campbell Hoffman). However, I was initially struggling when trying to change the way the permissions worked within the plugin.

By default, only site administrators get to see the forms menu item in the Dashboard, and only they can edit forms, view submission data etc. I wanted to allow other roles (e.g. Contributors) to view submission data, but, ideally, not to edit forms, change advanced form settings etc, or edit posts etc. Therefore, I started looking around in the Form Manager plugin code to see if I could change things to allow different roles to do different things and was getting confused by things like the $fm_MEMBERS_EXISTS variable. What I should have done, as always, is look at the docs for the plugin, where I would have found (and eventually did find) this: http://www.campbellhoffman.com/form-manager-faq/#how-do-i-restrict-access-to-different-parts-of-form-manager-members

It turns out that the Form Manager plugin integrates with Justin Tadlock’s Member’s plugin, which in itself seems like an excellent plugin, allowing you to change the capabilities associated with different roles, create your own roles and more. As an aside, users, roles and capabilities in WordPress can be confusing, but Justin’s post on the what they all mean makes it much less so.

Therefore, combining these two plugins allowed me to create a new role that has very limited capabilities. Alongside the standard ‘read’ capability, all they can do is view the list of available forms (the ‘form_manager_main’ capability), view the submission data table (‘

In conclusion, I would say the Members plugin is a ‘must have’ if you want something other than the standard roles offered by WordPress and the Form Manager plugin, of which I was already a fan, is made all the better thanks to its ability to integrate with Members.