Pines Development

3.2. Pines Object

3.2.1. Running an Action
3.2.2. Accessing Sessions
3.2.3. Redirecting the User
3.2.4. Formatting Output
3.2.5. Checking an IP Address

As well as containing services and variables, the Pines object ($pines) also includes several useful methods.

3.2.1. Running an Action

To run an action, use the action method. Actions are run automatically when requested in the URL by the client. The "option" request variable determines the component to which the action belongs, and the "action" request variable determines which action to run. The action is run by the system init script i60action.php.

Sometimes, actions need to be run manually in code. For example, the default action (default.php in a component's action directory) can be used to direct the user to a common action by calling action.

When an action is run, action will look in the component's actions directory for a file with the same name as the desired action (with .php appended). If the desired component is "system", Pines will instead look in the system's actions directory. If no action was specified, action will look for a default.php file. If no component was specified, action will use the default component specified in Pines' configuration. Once the correct file is found, action will run the file. The $pines variable is already included when the file is run, so there is no need to include it with the global keyword.

[Note]Note

Since actions are run inside a function, they are not in the global scope. This means actions don't have to clean up variables and need not worry about naming collisions, unlike init scripts, which will be discussed later.

If no action file was found for the given arguments, action will throw a new 404 HttpClientException. Otherwise, it will return the value returned by the action file. If i60action.php catches a HttpClientException or a HttpServerException when it runs the requested action, it will attach a module with the system's "error" view into the page's "content" position and send the corresponding HTTP status code. This means your action can throw either of these exceptions (HttpServerException for a 5XX error, and HttpClientException for a 4XX error) and the HTTP status code will be sent to the client, along with an explanation of the error (or an optional message you provide).

Manually Running an Action

// Run a specific action.
$pines->action('com_example', 'widgets/list');

// Run a component's default action.
$pines->action('com_example');

// Run the default component's default action.
$pines->action();

3.2.2. Accessing Sessions

Sessions in Pines are handled exclusively through the session method. Using this method, you can access an existing session for reading or writing, and close or destroy it. Using this method to open a session for reading allows asynchronous requests to Pines to respond quickly, without blocking.

If you've never experienced blocking in PHP sessions, it occurs when a script has a session open for writing, and another script (or the same one in a different request) tries to open the same session. The second script will pause execution until the first script either closes the session or exits.

The session method takes one argument, the access type requested. It can be one of the following:

  • read

    Open the session for reading only. This is the default.

  • write

    Open the session for reading and writing.

  • close

    Close a session that was opened for writing. The session remains open for reading.

  • destroy

    Unset and destroy a session.

If you open a session for writing, you should always close it once you don't need write access anymore.

Reading Session Data

// Open the session for reading.
$pines->session('read');

// Also works.
$pines->session();

// Now the session variable is full of the session data.
echo $_SESSION['messages'];

Writing Session Data

// Open the session for writing.
$pines->session('write');
// Now use the session variable normally.
$_SESSION['messages'] = '';

foreach ($messages as $cur_message) {
    if (empty($cur_message)) {
        // If you exit out of the script, remember to close the session.
        $pines->session('close');
        pines_error('Broken message encountered.');
        return;
    }
    $_SESSION['messages'] .= " $cur_message";
}

// Now that we're done, close the session.
$pines->session('close');
pines_notice('Messages saved.');

3.2.3. Redirecting the User

The Pines object includes redirect, a method to redirect users to a different URL. Using this method ensures that any messages and errors that are queued to be displayed to the user will be displayed when the user reaches the destination URL, assuming that URL is also handled by the same Pines installation. The HTTP status code returned to the client can be changed and defaults to 303 (See Other).

Redirecting the User

// Notices and errors will be saved.
pines_notice('You have been redirected here.');
$pines->redirect(pines_url('com_example', 'widgets/list'));

// Redirect to the homepage.
$pines->redirect(pines_url());

// Use a permanent redirection code.
$pines->redirect(pines_url('com_example', 'widgets/list'), 301);

3.2.4. Formatting Output

There are several types of content that need to be formatted correctly before being output to the user. The Pines object provides functions to allow easy formatting of this data.

3.2.4.1. Formatting Content

To format content, use format_content. By itself, format_content does nothing. Its purpose is to provide a way for components to alter content before it is shown to the client. By using this method to format your component's content before outputting it, you allow other components to use the hooking system to provide special alterations to your content. This is meant to provide things like string replacements, inline modules, HTML cleansers, etc. This does not mean you should always run content through this method. Certain types of content, such as page text, blog post text, product descriptions, etc are appropriate for content formatting. However, content such as user comments, forum posts, etc may allow an unprivileged user to use dangerous services if run through the formatter. A good idea may be to use a configuration option to allow certain content to be altered by other components. Generally only user provided content should ever be formatted. Content like your component's forms should most likely never be formatted.

Formatting Content for Output
<div>
    <?php echo $pines->format_content($post->content); ?>
</div>

As mentioned, components can hook this function to provide special alterations to content. See the Hook section in Core Services for information about hooks.

Using a Hook to Alter Content
// Replace the word "Pines" with "Barbecue".
function com_example__replace(&$arguments) {
    $arguments[0] = str_replace('Pines', 'Barbecue', $arguments[0]);
}

$pines->hook->add_callback('$pines->format_content', -10, 'com_example__replace');

3.2.4.2. Formatting a Date / Time

To format a date or time using a timestamp, use format_date. The current user's timezone is automatically loaded by the user manager and used for calculations. You can also pass format_date a timezone to use. When using a custom format, any format recognized by the format method of the DateTime class can be used. format_date supports several format types.

Table 3.1. Date Format Types

TypeFormat CodeDescription
full_sortY-m-d H:i TDate and time, big endian and 24 hour format so it is sortable.
full_longl, F j, Y g:i A TDate and time, long format.
full_medj M Y g:i A TDate and time, medium format.
full_shortn/d/Y g:i A TDate and time, short format.
date_sortY-m-dOnly the date, big endian so it is sortable.
date_longl, F j, YOnly the date, long format.
date_medj M YOnly the date, medium format.
date_shortn/d/YOnly the date, short format.
time_sortH:i TOnly the time, 24 hour format so it is sortable.
time_longg:i:s A TOnly the time, long format.
time_medg:i:s AOnly the time, medium format.
time_shortg:i AOnly the time, short format.
custom(Contents of $format)Use whatever is passed in $format.


Formatting a Date
<div>
    <?php echo htmlspecialchars($pines->format_date($timestamp, 'custom', 'l jS \of F Y h:i:s A', 'America/Los_Angeles')); ?>
</div>

3.2.4.3. Formatting a Date Range

To format a date or time range using two timestamps, use format_date_range. Like format_date, the current user's timezone is used for calculations. One wouldn't think that a timezone would be a concern when showing a range of time, but if your time range displays hours and a Daylight Savings Time change occurs during it in the selected timezone, you will have a different number of hours than in a timezone without DST.

$format is built using macros, which are substrings replaced by the corresponding number of units. There are singular macros, such as #year#, which are used if the number of that unit is 1. For example, if the range is 1 year and both #year# and #years# are present, #year# will be used and #years# will be ignored. This allows you to use a different description for each one. You accomplish this by surrounding the macro and its description in curly brackets. If the unit is 0, everything in that curly bracket will be removed. This allows you to place both #year# and #years# and always end up with the right one.

Since the units in curly brackets that equal 0 are removed, you can include as many as you want and only the relevant ones will be used. If you choose not to include one, such as year, then the next available one will include the time that would have been placed in it. For example, if the time range is 2 years, but you only include months, then months will be set to 24.

After formatting, any leading and trailing whitespace is trimmed before the result is returned.

Table 3.2. Macros Available in Date Range Formats

MacroCorresponding Value
#years#The number of years.
#year#The number 1 if applicable.
#months#The number of months.
#month#The number 1 if applicable.
#weeks#The number of weeks.
#week#The number 1 if applicable.
#days#The number of days.
#day#The number 1 if applicable.
#hours#The number of hours.
#hour#The number 1 if applicable.
#minutes#The number of minutes.
#minute#The number 1 if applicable.
#seconds#The number of seconds.
#second#The number 1 if applicable.


If $format is left null, it defaults to the following: "{#years# years}{#year# year} {#months# months}{#month# month} {#days# days}{#day# day} {#hours# hours}{#hour# hour} {#minutes# minutes}{#minute# minute} {#seconds# seconds}{#second# second}"

Here are some examples of formats and what would be returned given a time range of 2 years 5 months 1 day and 4 hours. (These values were calculated on Fri Oct 14 2011 in San Diego, which has DST. 2012 is a leap year.)

  • #years# years {#days# days}{#day# day}

    2 years 152 days

  • {#months# months}{#month# month} {#days# days}{#day# day}

    29 months 1 day

  • {#weeks# weeks}{#week# week} {#days# days}{#day# day}

    126 weeks 1 day

  • #days# days #hours# hours #minutes# minutes

    883 days 4 hours 0 minutes

  • {#minutes#min} {#seconds#sec}

    1271760min

  • #seconds#

    76305600

Formatting a Date Range
<div>
    This warehouse has gone
    <?php echo htmlspecialchars($pines->format_date_range($last_accident, time(), '{#days# days}{#day# day}', 'America/Los_Angeles')); ?>
    without an accident.
</div>

3.2.4.4. Formatting a Fuzzy Time String

To format a fuzzy time string using a timestamp, use format_fuzzy_time. This method does not use timezones, so it may not give perfectly precise time strings. Seeing as it is used for a time estimation, that shouldn't be a problem.

Formatting a Fuzzy Time String
<div>
    Sale created <?php echo htmlspecialchars($pines->format_fuzzy_time($sale->p_cdate)); ?>.
</div>

3.2.4.5. Formatting a Phone Number

To format a phone number, use format_phone. It uses US phone number format. E.g. "(800) 555-1234 x56".

Formatting a Phone Number
<div>
    <?php echo htmlspecialchars($pines->format_phone('1800555123456')); ?>
</div>

3.2.5. Checking an IP Address

There are three methods of checking whether an IP address is on a given network in the Pines object.

Using CIDR Notation

You can use check_ip_cidr to check an IP address using the CIDR notation of a network.

Checking an IP Using CIDR Notation
$good = $pines->check_ip_cidr('192.168.0.5', '192.168/24'); // Returns true.

$bad = $pines->check_ip_cidr('192.168.1.5', '192.168/24'); // Returns false.

Using an IP Range

You can use check_ip_range to check an IP address using an IP range.

Checking an IP Using an IP Range
$good = $pines->check_ip_range('192.168.0.5', '192.168.0.0', '192.168.0.255'); // Returns true.

$bad = $pines->check_ip_range('192.168.1.5', '192.168.0.0', '192.168.0.255'); // Returns false.

Using a Subnet Mask

You can use check_ip_subnet to check an IP address using the subnet mask of a network.

Checking an IP Using a Subnet Mask
$good = $pines->check_ip_subnet('192.168.0.5', '192.168.0.0', '255.255.255.0'); // Returns true.

$bad = $pines->check_ip_subnet('192.168.1.5', '192.168.0.0', '255.255.255.0'); // Returns false.