Generic method to add icons for custom fields

On August 3, 2014, in Mantis, by terencejackson

Hi,

Normally if you have a bug in your system you want to have an effort estimate for it. In some cases it is enough to get an estimate if the effort is high, medium or low. In Mantis you can create a custom field for it. At least I do this for all my projects 😉

The values will then be displayed as a text in your view issues page, but since all people are very visual I wanted to have icons here to clearly see which efforts are high and which are low. Unfortunately there is no easy way to do this in the current version of Mantis. That’s why I hit the keys and created a small enhancement to show icons for all custom fields, if you want to show icons for them.

The result for the effort looks like this after my enhancement:

effort

 

You can download the Patch and the images directly here.

The following files are affected by the patch:

The following configuration parameter has to be added in config_defaults_inc.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * Associative Array for icons for custom fields
 * <Custom Field Name> => array ("Single Values" => "Picture"). Always add ShowText as an option. If it is set to ON the text is displayed in addition to the icon.
 * @global array $g_custom_status_icon_arr
 */
$g_custom_status_icon_arr = array (
        "Effort" => array(
                "" => "none.png",
                "Low" => "low.png",
                "Medium" => "medium.png",
                "High" => "high.png",
                "ShowText" => OFF
        )
);
/**
 * Associative Array for icons for custom fields
 * <Custom Field Name> => array ("Single Values" => "Picture"). Always add ShowText as an option. If it is set to ON the text is displayed in addition to the icon.
 * @global array $g_custom_status_icon_arr
 */
$g_custom_status_icon_arr = array (
		"Effort" => array(
				"" => "none.png",
				"Low" => "low.png",
				"Medium" => "medium.png",
				"High" => "high.png",
				"ShowText" => OFF
		)
);

If you want to add icons for a new custom field (e.g. module) you simply have to add it to the array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$g_custom_status_icon_arr = array (
        "Effort" => array(
                "" => "none.png",
                "Low" => "low.png",
                "Medium" => "medium.png",
                "High" => "high.png",
                "ShowText" => OFF
        ),
                "Effort" => array(
                "User Management" => "userManagement.png",
                "Contracts" => "contracts.png",
                "ShowText" => ON
        )
);
$g_custom_status_icon_arr = array (
		"Effort" => array(
				"" => "none.png",
				"Low" => "low.png",
				"Medium" => "medium.png",
				"High" => "high.png",
				"ShowText" => OFF
		),
                "Effort" => array(
				"User Management" => "userManagement.png",
				"Contracts" => "contracts.png",
				"ShowText" => ON
		)
);

With switching the ShowText property to ON the text is shown right to the icon.

The method print_custom_field_value has to be replaced by the following source code in custom_field_api.php:

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
function print_custom_field_value( array $p_def, $p_field_id, $p_bug_id ) {
    $f_icon_set = get_icon_set_for_field($p_def["name"]);
    $f_print_value = "";
    if($f_icon_set->icon_set_exists){
        $f_icon_path = config_get( 'icon_path' );
        $f_custom_field_value = custom_field_get_value( $p_field_id, $p_bug_id );
        $f_print_value .= '<img src="' . $f_icon_path . $f_icon_set->icon_array[$f_custom_field_value] . '" alt="" title="' . $f_custom_field_value . '" />';
    }
    if(!$f_icon_set->icon_set_exists || (array_key_exists("ShowText", $f_icon_set->icon_array) && $f_icon_set->icon_array["ShowText"] == ON)) {
        $f_print_value .= string_custom_field_value( $p_def, $p_field_id, $p_bug_id );
    }
    echo $f_print_value;
}
 
/**
* Check if an icon set is defined for the given parameter
* @param String $p_name The name of the field to look up
* @return mixed stdClass with the values icon_set_exists (True if icon set exists) and icon_array (the array with the icons)
*/
function get_icon_set_for_field($p_name){
    $f_custom_status_icon_arr = config_get("custom_status_icon_arr", array());
    $f_return = new stdClass;
    $f_return->icon_set_exists = array_key_exists($p_name, $f_custom_status_icon_arr);
    $f_return->icon_array = $f_custom_status_icon_arr[$p_name];
    return $f_return;
}
function print_custom_field_value( array $p_def, $p_field_id, $p_bug_id ) {
	$f_icon_set = get_icon_set_for_field($p_def["name"]);
	$f_print_value = "";
	if($f_icon_set->icon_set_exists){
		$f_icon_path = config_get( 'icon_path' );
		$f_custom_field_value = custom_field_get_value( $p_field_id, $p_bug_id );
		$f_print_value .= '<img src="' . $f_icon_path . $f_icon_set->icon_array[$f_custom_field_value] . '" alt="" title="' . $f_custom_field_value . '" />';
	}
	if(!$f_icon_set->icon_set_exists || (array_key_exists("ShowText", $f_icon_set->icon_array) && $f_icon_set->icon_array["ShowText"] == ON)) {
		$f_print_value .= string_custom_field_value( $p_def, $p_field_id, $p_bug_id );
	}
	echo $f_print_value;
}

/**
* Check if an icon set is defined for the given parameter
* @param String $p_name The name of the field to look up
* @return mixed stdClass with the values icon_set_exists (True if icon set exists) and icon_array (the array with the icons)
*/
function get_icon_set_for_field($p_name){
	$f_custom_status_icon_arr = config_get("custom_status_icon_arr", array());
	$f_return = new stdClass;
	$f_return->icon_set_exists = array_key_exists($p_name, $f_custom_status_icon_arr);
	$f_return->icon_array = $f_custom_status_icon_arr[$p_name];
	return $f_return;
}
Tagged with:  

Improve Mantis password security

On August 1, 2014, in Mantis, by terencejackson

Hi,

it’s me again. It’s been a long time since I developed something which mostly has to do with a new job I started around a year ago. Nevertheless I have to deal with Mantis in this new job and I really like Mantis. But unfortunately the password security is not very sophisticated in the current version 1.2.17. You can enter simple passwords like 1 or 2, … which are not really secure passwords 😉
To improve the password security you can download and apply the patches which I developed to solve this problem. The zip files contains two patches, and you need to apply both to make it work.

The following changes have been performed to make the password more secure:
The following lines have been added to file config_defaults_inc.php (Here you can overwrite the values if you want e.g. a longer password):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
* Configuration for the password security.
* If NUMBER_REQUIRED = true at least one number is required
* IF UPPERCASE_REQUIRED = true at least one uppercase character is required
* IF LOWERCASE_REQUIRED = true at least one lowercase character is required
* MIN_CHARACTERS defines the minumum characters
* @global mixed $g_password_security
*/
$g_password_security = array (
  "NUMBER_REQUIRED" => true,
  "UPPERCASE_REQUIRED" => true,
  "LOWERCASE_REQUIRED" => true,
  "MIN_CHARACTERS" => 8
);
/**
* Configuration for the password security.
* If NUMBER_REQUIRED = true at least one number is required
* IF UPPERCASE_REQUIRED = true at least one uppercase character is required
* IF LOWERCASE_REQUIRED = true at least one lowercase character is required
* MIN_CHARACTERS defines the minumum characters
* @global mixed $g_password_security
*/
$g_password_security = array (
  "NUMBER_REQUIRED" => true,
  "UPPERCASE_REQUIRED" => true,
  "LOWERCASE_REQUIRED" => true,
  "MIN_CHARACTERS" => 8
);

The if statement starting in line 111 in account_update.php has been replaced by the following statement:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// Update password if the two match and are not empty
if (! is_blank ( $f_password )) {
  if ($f_password != $f_password_confirm) {
    trigger_error ( ERROR_USER_CREATE_PASSWORD_MISMATCH, ERROR );
  } else {
    $f_password_security = config_get ( 'password_security' );
    $f_uppercase = $f_password_security ["UPPERCASE_REQUIRED"] ? preg_match ( '/[A-Z]/', $f_password ) : 1;
    $f_lowercase = $f_password_security ["LOWERCASE_REQUIRED"] ? preg_match ( '/[a-z]/', $f_password ) : 1;
    $f_number = $f_password_security ["NUMBER_REQUIRED"] ? preg_match ( '/[0-9]/', $f_password ) : 1;
    $f_length = $f_password_security ["MIN_CHARACTERS"];
 
    if (! $f_uppercase || ! $f_lowercase || ! $f_number || strlen ( $f_password ) < $f_length) {
      trigger_error ( ERROR_USER_CREATE_PASSWORD_PATTERN_NO_MATCH, ERROR );
    } else if (! auth_does_password_match ( $t_user_id, $f_password )) {
      user_set_password ( $t_user_id, $f_password );
      $t_password_updated = true;
    }
  }
}
// Update password if the two match and are not empty
if (! is_blank ( $f_password )) {
  if ($f_password != $f_password_confirm) {
    trigger_error ( ERROR_USER_CREATE_PASSWORD_MISMATCH, ERROR );
  } else {
    $f_password_security = config_get ( 'password_security' );
    $f_uppercase = $f_password_security ["UPPERCASE_REQUIRED"] ? preg_match ( '/[A-Z]/', $f_password ) : 1;
    $f_lowercase = $f_password_security ["LOWERCASE_REQUIRED"] ? preg_match ( '/[a-z]/', $f_password ) : 1;
    $f_number = $f_password_security ["NUMBER_REQUIRED"] ? preg_match ( '/[0-9]/', $f_password ) : 1;
    $f_length = $f_password_security ["MIN_CHARACTERS"];

    if (! $f_uppercase || ! $f_lowercase || ! $f_number || strlen ( $f_password ) < $f_length) {
      trigger_error ( ERROR_USER_CREATE_PASSWORD_PATTERN_NO_MATCH, ERROR );
    } else if (! auth_does_password_match ( $t_user_id, $f_password )) {
      user_set_password ( $t_user_id, $f_password );
      $t_password_updated = true;
    }
  }
}

An additional string has been added in strings_english.txt:

1
$MANTIS_ERROR[ERROR_USER_CREATE_PASSWORD_PATTERN_NO_MATCH] = 'Please enter a valid password!';
$MANTIS_ERROR[ERROR_USER_CREATE_PASSWORD_PATTERN_NO_MATCH] = 'Please enter a valid password!';

I hope you enjoy this enhancement!

Tagged with:  

Java BreweryDB Connector – Version 0.0.3

On August 13, 2013, in JavaBreweryDBConnector, by terencejackson

Hi Guys,

today I published the version 0.0.3-SNAPSHOT of the Java BreweryDB Connector. It is a connector written it Java to get data of http://www.brewerydb.com/. You can find the Java BreweryDB Connector on Github: https://github.com/terencejackson/JavaBreweryDbConnector

With this version the following new functionality is introduced:

  • Asynchronous beer service
  • Asynchronous guice module
  • Synchronous guice module

To use it in your application you have to put the following in you pom.xml:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<repositories>
    <repository>
        <id>JavaBreweryDbConnector</id>
        <url>https://raw.github.com/terencejackson/JavaBreweryDbConnector/mvn-repo/</url>
        <snapshots>
            <enabled>true</enabled>
            <updatePolicy>always</updatePolicy>
        </snapshots>
    </repository>
</repositories>
 
<dependency>
    <groupId>com.tj.brewerydb</groupId>
    <artifactId>connector</artifactId>
    <version>0.0.3-SNAPSHOT</version>
</dependency>
<repositories>
    <repository>
        <id>JavaBreweryDbConnector</id>
        <url>https://raw.github.com/terencejackson/JavaBreweryDbConnector/mvn-repo/</url>
        <snapshots>
            <enabled>true</enabled>
            <updatePolicy>always</updatePolicy>
        </snapshots>
    </repository>
</repositories>

<dependency>
    <groupId>com.tj.brewerydb</groupId>
    <artifactId>connector</artifactId>
    <version>0.0.3-SNAPSHOT</version>
</dependency>

If you are using Google Guice you can use the connector as followed:

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
System.out.println("start");
 
// Create the injector, the async module creates the sync and async object
Injector injector = Guice.createInjector(new BreweryDBAsyncModule());
 
// Get the sync service
final IBreweryDBService syncService = injector
        .getInstance(IBreweryDBService.class);
// Do some sync calls
Beer result = syncService.getBeerById("cBLTUw");
System.out.println("Sync: " + result);
//Get beers by name
List<Beer> salvator = syncService.getAllBeers(BeersFilter.createNameFilter("Salvator"));
System.out.println("Sync: " + salvator);
 
// Get the async service
final IBreweryDBServiceAsync asyncService = injector
        .getInstance(IBreweryDBServiceAsync.class);
 
// Do some async calls
asyncService.getAllBeers(new IResultCallback<List<Beer>>() {
 
    public void onSuccess(List<Beer> result) {
        System.out.println(result);
    }
 
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }
});
 
asyncService.getBeerById("cBLTUw", new IResultCallback<Beer>() {
 
    public void onSuccess(Beer result) {
        System.out.println("Async:" + result);
    }
 
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }
});
 
System.out.println("Done");
System.out.println("start");

// Create the injector, the async module creates the sync and async object
Injector injector = Guice.createInjector(new BreweryDBAsyncModule());

// Get the sync service
final IBreweryDBService syncService = injector
        .getInstance(IBreweryDBService.class);
// Do some sync calls
Beer result = syncService.getBeerById("cBLTUw");
System.out.println("Sync: " + result);
//Get beers by name
List<Beer> salvator = syncService.getAllBeers(BeersFilter.createNameFilter("Salvator"));
System.out.println("Sync: " + salvator);

// Get the async service
final IBreweryDBServiceAsync asyncService = injector
        .getInstance(IBreweryDBServiceAsync.class);

// Do some async calls
asyncService.getAllBeers(new IResultCallback<List<Beer>>() {

    public void onSuccess(List<Beer> result) {
        System.out.println(result);
    }

    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }
});

asyncService.getBeerById("cBLTUw", new IResultCallback<Beer>() {

    public void onSuccess(Beer result) {
        System.out.println("Async:" + result);
    }

    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }
});

System.out.println("Done");

By default you have to provide a configuration.properties in your classpath with the following entry:

apiKey=YOURAPIKEY

Hope this post gets you started with the connector.

Tagged with:  

Features of the Beertracker

On August 6, 2013, in Beertacker, by terencejackson

Hi Guys,

I just introduced the Beertracker. This time I want to show you all the base features which are currently available if you use the Beertracker!

1) The login screen

To use the Beertracker you first have to sign in. To sign in you have several methods.

01 - Main page

 

  1. If you already have signed up you can use your username and password to login
  2. You can use your facebook account to login – The Beertracker asks for the permission of your email address and to post
  3. If you don’t want to use you facebook account you can register for a free account. You’ll have to sign up with your email address as username!

2) The dashboard

The dashboard shows you some statistics and offers other usefull features for the Beertracker.

02 - Dashboard

 

  1. Here you see statistics about the beers you already tracked and e.g. what the currently most famous beer is (Tracked by the most people).
  2. Here you can directly enter a beer you want to lookup and add it to your profile. You will get directly to the “add beers” page.
  3. Here you can get to your profile.
  4. Here you can add beers to your profile.
  5. Here you get to the page where you can find your tracked beers as a list
  6. Here you get to the page where you can find your tracked beers on a map based on the location of the brewery.
  7. Here you can logout of the application. This button is on the same spot in the whole application.

3) My profile

On the profile page you get information about the profile you are currently signed in to the Beertracker.

03 - My profile

 

  1. Here you see your account information like your username and the last added beer.
  2. Here you see information about the facebook account you have assigned to your profile
  3. Here you can allow the Beertracker to post a message to facebook if you add a new beer to your profile. (If you do a mass update when you’re newly using the Beertracker it is recommended to turn the post of new messages of for this time, after that, please turn it on again 😉 )

4) Search for beers and add them to your profile

If you click on the “Add beers” button or use the quick search of the dashboard you’ll get the the page where you can add beers to your profile.

04 - Add beers

 

  1. Here you enter the name of the beer you want to add to your profile. You must enter at least 3 characters, otherwise nothing will be found!
  2. Here you see the result list of your entered name of the beer.
  3. With the add button you can add the beer to your profile.
  4. This is the success message if the beer was added successfuly to your account.

5) Your beers – list

If you click on the “My beers” button you’ll get a list of your tracked beers.

05 - My beers list

 

  1. Here you can enter a filter for the list of your beers.
  2. Here you see the filtered list of your beers.
  3. With the “minus button” you can remove a beer from your list.

5) Your beers – map

If you click on the “Beer map” button you’ll get a map of your tracked beers.

06 - My beers map

The beers are marked on the map by the location of the brewery they are brewed.


Upcoming features

Here are some ideas for upcoming features, if you have any ideas or wishes, just leave a comment or write me an email.

  • Google login
  • Quests: Quests like “The Paulaner Quest” which you solve by trinking all beers of the Paulaner brand.
  • “Find my next beer”: Based on your location find a bar which offers a beer you haven’t drunk yet

If you’re looking for a beer an cannot find it in the Beertracker, feel free to go to http://www.brewerydb.com/ (A fantastic project!!!) and add your beer there and it will appear in the Beertracker soon… 😉

Cheers!

Tagged with:  

Introducing the Beertracker

On August 6, 2013, in Beertacker, by terencejackson

Hi Guys,

this time I want to introduce the brand new Beertracker!

Track the beers you drank and show the world how international you are

It’s that simple! With the Beertracker you can track the beers you already drunk in your life. So if you go to a bar and want to try something new, just look at the Beertracker and the menu and decide which beer you gonna drink next! Go, get em all 😉

You can access the Beertracker under the following link: http://my-beertracker.com

You can sign up a new account or just login with your facebook account!

A description of the features can be found here.

I hope you enjoy tracking your beers!

Cheers!

Tagged with:  

Adding custom css to primefaces mobile jsf page

On August 2, 2013, in JSF, Mobile, Primefaces, by terencejackson

Hi Guys,

if you want to add custom css to your Primefaces Mobile page you habe to use a facet. First of all you have to store your css in a folder located in src/main/webapp (for instance src/main/webapp/resources/css/style.css).

After that you have to include your css in the postInit facet in your page:

1
2
3
4
5
<pm:page >
  <f:facet name="postinit">
    <link type="text/css" rel="stylesheet"href="#{resource['css:style.css']}" />
  </f:facet>
</pm:page>
<pm:page >
  <f:facet name="postinit">
    <link type="text/css" rel="stylesheet"href="#{resource['css:style.css']}" />
  </f:facet>
</pm:page>

#{resource[‘css:style.css’]} means: Lookup a css file named style.css in the resource folder (library).

That’s it, now you can use your css in your page just like:

<p:outputPanel id="container" layout="block" styleClass="<strong>customClass</strong>">

 

Tagged with:  

Beertracker – Beta tester

On July 22, 2013, in Beertacker, Beta, by terencejackson

Hi Guys,

I am looking for beta testers of my new app – the BEERTRACKER!

What is the BEERTRACKER?

With the BEERTRACKER you can track what kind of beers you have already drunk in your life. This makes it simple if you go to a bar, looking for a new kind of taste, you can just look at your BEERTRACKER, see what beers you’ve already drunk an choose the new flovour you want to try!

How can I sign up for the BEERTRACKER?

The current BEERTRACKER is available here: http://beers-sosv.rhcloud.com/. A better URL is coming up in the next weeks…
If you visit the page just click on register and sign up with a valid email address and a password.

Is there a bugtracker?

Yes, there is. If you are interested in beta testing the application, just write me an email svensommerfeld1982(at)gmail.com and I’ll create a bugtracker account for you.

I hope you’ll join me in the beta testing phase!

Tagged with:  

Using MGWT TabPanel with UIBinder

On February 21, 2013, in GWT, by terencejackson

If you want to create an application with GWT which has the focus on mobile devices you can either use JQueryMobile and GWT or MGWT. With both libraries you get mobile feeling like touch support, scrolling without scrollbars, …

Sice I am trying to implement some demo applications with MGWT I tried to use the TabPanel feature. It is a really nice out of the box control which is pretty easy to use if you create it in “code behind”.

MGWT - TabPanel

 

Since I am not a big fan of implementing a view I decided to use the GWT UiBinder which is delivered in the GWT SDK and allows you to describe your UI. To use th tab panel with the UIBinder you’ll get the following instruction as comment of the class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 So if you want to use TabPanel in UIBinder its a bit choppy:
 
 <pre>
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
 </mgwt:TabPanel>
 </pre>
 So if you want to use TabPanel in UIBinder its a bit choppy:

 <pre>
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
 </mgwt:TabPanel>
 </pre>

The mgwt namespace has to be defined in the package com.googlecode.mgwt.ui.client.widget.tabbar.

What you would suggest is if you want to add a new tab you simply add it to the <mgwt:tabs> tag  just like in the example below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab 2-->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
 </mgwt:TabPanel>
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
			  <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab 2-->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
 </mgwt:TabPanel>

Unfortunaley this leads to the following exception: Can only have one element per @UiChild parser tag.

Which means, the tabs can only have one tab inside!

To solve this problem you just have to add multiple <mgwt:tabs> tags. Each for every tab you want. That’s it! A simple example is shown below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
      <mgwt:tabs>
                  <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab 2-->
                      </mgwt:widget>
              </mgwt:Tab>
        </mgwt:tabs>
 </mgwt:TabPanel>
 <mgwt:TabPanel>
      <mgwt:tabs>
              <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab -->
                      </mgwt:widget>
              </mgwt:Tab>
      </mgwt:tabs>
	  <mgwt:tabs>
	  			  <mgwt:Tab>
                      <mgwt:button>
                              <mgwt:DownloadsTabBarButton></mgwt:DownloadsTabBarButton>
                      </mgwt:button>
                      <mgwt:widget>
                              <!-- content for that tab 2-->
                      </mgwt:widget>
              </mgwt:Tab>
		</mgwt:tabs>
 </mgwt:TabPanel>

 

Tagged with:  

Yet another php array helper class

On September 1, 2012, in PHP, by terencejackson

Hi,

in each PHP project you implement you have to handle with arrays. You need some elements of the array or you have to delete some elements of the array or even have to transform the elements of the array. What you need are foreach loops each time you want to use it (If you did’nt encapsulate it in an own class).

Inspired by some fantastic methods of guava iterables, the LINQ extensions methods and the problems mentioned above I decided to create a static array helper class which handles problems like search and delete in a easy to understand syntax.

For a better understanding here are some examples of the array helper class.

For the tests I always use the following class and the following array:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person{
public $age;
public $name;
 
public function __construct($name, $age){
$this->name = $name;
$this->age = $age;
}
}
 
function createDemoArray(){
$array = array();
array_push($array, new Person("Mister X.", 40));
array_push($array, new Person("Mister Y.", 50));
array_push($array, new Person("Mister Z.", 60));
array_push($array, new Person("Mister Y.", 70));
return $array;
}
class Person{
public $age;
public $name;

public function __construct($name, $age){
$this->name = $name;
$this->age = $age;
}
}

function createDemoArray(){
$array = array();
array_push($array, new Person("Mister X.", 40));
array_push($array, new Person("Mister Y.", 50));
array_push($array, new Person("Mister Z.", 60));
array_push($array, new Person("Mister Y.", 70));
return $array;
}

1) Get all person which are younger than 50 without additional parameter:

1
2
3
$result =<strong> Arrays::filter</strong>($array, function($person) {return $person->age <= 50;});
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) [1] => Person Object ( [age] => 50 [name] => Mister Y. ) )
$result =<strong> Arrays::filter</strong>($array, function($person) {return $person->age <= 50;});
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) [1] => Person Object ( [age] => 50 [name] => Mister Y. ) )

2) Get all person which are younger than 49 with additional parameter:

1
2
3
$result = Arrays::filter($array, function($person, $maxAge) {return $person->age <= $maxAge;},49);
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) )
$result = Arrays::filter($array, function($person, $maxAge) {return $person->age <= $maxAge;},49);
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) )

3) Is there a person called “Mister X.” (any):

1
2
3
$result = Arrays::any($array, function($person) { return $person->name == "Mister X."; });
print_r($result);
Result: 1
$result = Arrays::any($array, function($person) { return $person->name == "Mister X."; });
print_r($result);
Result: 1

4):Is there a person called “Mister X.” (any with parameter)

1
2
3
$result = Arrays::any($array, function($person, $name) { return $person->name == $name;}, "Mister X.");
print_r($result);
Result: 1
$result = Arrays::any($array, function($person, $name) { return $person->name == $name;}, "Mister X.");
print_r($result);
Result: 1

5) Get the first person who is called “Mister Y.” (first):

1
2
3
$result = Arrays::first($array, function($person, $name) { return $person->name == $name;}, Mister Y.");
print_r($result);
Result: Person Object ( [age] => 70 [name] => Mister Y. )
$result = Arrays::first($array, function($person, $name) { return $person->name == $name;}, Mister Y.");
print_r($result);
Result: Person Object ( [age] => 70 [name] => Mister Y. )

6)Delete all persons called “Mister Y.” (delete):

1
2
3
$result = Arrays::delete($array, function($person, $name) {return $person->name == $name;}, "Mister Y.");
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) [2] => Person Object ( [age] => 60 [name] => Mister Z.)
$result = Arrays::delete($array, function($person, $name) {return $person->name == $name;}, "Mister Y.");
print_r($result);
Result: Array ( [0] => Person Object ( [age] => 40 [name] => Mister X. ) [2] => Person Object ( [age] => 60 [name] => Mister Z.)

7) Transform all persons to a string array with the names (transform):

1
2
3
$result = Arrays::transform($array, function($person) {return $person->name;});
print_r($result);
Array ( [0] => Mister X. [1] => Mister Y. [2] => Mister Z. [3] => Mister Y. )
$result = Arrays::transform($array, function($person) {return $person->name;});
print_r($result);
Array ( [0] => Mister X. [1] => Mister Y. [2] => Mister Z. [3] => Mister Y. )

As you can see things like looking up an element of an array is a one liner now 😉

You can download the class here.

If you have any suggestions or bug reports, just leave a comment…

Hope you enjoy my little PHP array helper.

Cheers!

Tagged with:  

Version 1.0.0

On May 17, 2012, in mod_most_popular_files, by terencejackson

Hi Guys,

the beta phase is over. You can download version 1.0.0 here.

There is also one new feature in this version. This feature was requested by Andy R and I put it in the 1.0.0.

The new feature is, that you can now choose if you just want to show the most popular files for the currently logged in user. This feature is turned off by default, but you can turn it on in the options.

There are three different modes for the feature which you can choose in the dropdown:

  • NO: The most popular files are calculated based on all users, not only the logged in one (default setting)
  • YES: The most popular files are calculated based on the logged in user. If no user is logged in the result is 0 popular files.
  • EXTENDED: The most popular files are calculated based on the logged in user, but if no user is logged in  the most popular files are calculated based on all users.

You can also provide a “No files available message” which is displayed, if no most popular files can be shown to the current user/visitor of your page.

I hope you enjoy the module. If you have any further wishes, comments, critic, just leave a comment.