# PHP explode parts of ics file



## Damonc (May 9, 2001)

I've never used the 'explode' feature of php before, but what I'm trying to do is take parts of a ics (calendar) file and echo them out..

so the file is like this: (There is only one 'event' here but the actual thing will have more on different days)


```
BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:Australia/Sydney
BEGIN:STANDARD
TZOFFSETFROM:+1100
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
DTSTART:20080406T030000
TZNAME:AEST
TZOFFSETTO:+1000
END:STANDARD
BEGIN:DAYLIGHT
TZOFFSETFROM:+1000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
DTSTART:20081005T020000
TZNAME:AEDT
TZOFFSETTO:+1100
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
PRIORITY:5
DTEND;TZID=Australia/Sydney:20130710T213000
UID:d264b3f8-0c1f-46c4-9d0e-0b944673c008
DTSTAMP:20130710T101555Z
SEQUENCE:0
CLASS:PUBLIC
X-LABEL:0
SUMMARY:test test test
DTSTART;TZID=Australia/Sydney:20130710T203000
END:VEVENT
END:VCALENDAR
```
so what I'd like to do is echo out just these two lines after the ":" for each event.. 

```
SUMMARY:test test test
DTSTART;TZID=Australia/Sydney:20130710T203000
```
Now the tricky part.. is it possible to get it to only display the events for that day by reading the date from the DTSART line? (or at least put those at the top?)


----------



## JiminSA (Dec 15, 2011)

You can utilise explode to translate your text lines into an array by using the line-feed delimiter and then do a preg search on that array to get the array occurence (line number/array element) which contains whatever search pattern you want. From there you have a start point to manipulate your echo displays as you want (I used SUMMARY as my search pattern) which enabled me to locate the DTSTART line (which will always be +1 from your found line, I would think)

```
<?php

$text = "BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:Australia/Sydney
BEGIN:STANDARD
TZOFFSETFROM:+1100
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1SU
DTSTART:20080406T030000
TZNAME:AEST
TZOFFSETTO:+1000
END:STANDARD
BEGIN:DAYLIGHT
TZOFFSETFROM:+1000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU
DTSTART:20081005T020000
TZNAME:AEDT
TZOFFSETTO:+1100
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
PRIORITY:5
DTEND;TZID=Australia/Sydney:20130710T213000
UID:d264b3f8-0c1f-46c4-9d0e-0b944673c008
DTSTAMP:20130710T101555Z
SEQUENCE:0
CLASS:PUBLIC
X-LABEL:0
SUMMARY:test test test
DTSTART;TZID=Australia/Sydney:20130710T203000
END:VEVENT
END:VCALENDAR";

$text_array = explode( "\n", $text );

echo '';
print_r($text_array);
echo '';

$keyword = "SUMMARY";
$key = preg_grep("/{$keyword}/i",$text_array);
foreach($key as $sub=> $value)
{
echo "Found in Line No. = " . $sub . " Value =  " . $value . "
";
}
echo "Next Line = " . $text_array[$sub+1] . "
";
?>
```
Hope this helps


----------



## Damonc (May 9, 2001)

Awesome thanks!.. I'll let you know how I go


----------



## Damonc (May 9, 2001)

is it possible to modify this bit of code


```
<?php
$text_array = explode( "\n", $text );

$keyword = "SUMMARY"; 
$key = preg_grep("/{$keyword}/i",$text_array); 
foreach($key as $sub=> $value) 
{ 
echo "Found in Line No. = " . $sub . " Value =  " . $value . "
"; 
} 
echo "Next Line = " . $text_array[$sub+1] . "
"; 
?>
```
that returns this:

```
Found in Line No. = 26 Value = SUMMARY:test test test 
Next Line = DTSTART;TZID=Australia/Sydney:20130710T203000
```
to only return say this:

```
test test test 
Australia/Sydney:20130710T203000
```
sorry if that seems like a dumb question, but as I said I've never used explode before.


----------



## JiminSA (Dec 15, 2011)

Yes by further using explode ...

```
$line1 = explode(":", $text_array[$sub]);
$line2 = explode("=", $text_array[$sub+1]);
echo $line1[1] . "
";
echo $line2[1] . "
";
```


----------



## Damonc (May 9, 2001)

You are a legend..

Do you do this for a living or something? pretty sure you've helped me with my php questions before


----------



## JiminSA (Dec 15, 2011)

I do Website Design and Development to augment my income (I'm a pensioner), but enjoy helping people if I can ...


----------



## Damonc (May 9, 2001)

ahh ok.. Can I pick your brain once more?


----------



## JiminSA (Dec 15, 2011)

Certainly mate ...


----------



## Damonc (May 9, 2001)

I haven't tried it yet, but can I use something like this to generate the keyword?


```
$keyword = date ("Ymd")
```
instead of using "Summary" as a keyword? (that way hoping it will only echo back the events from the current day)


----------



## JiminSA (Dec 15, 2011)

The date and time stamp in your log are in a very specific format, so you would need to inspect each of the DTSTAMP lines

```
DTSTAMP:20130710T101555Z
```
that are present and find today's entry. Now if your Ymd equates 20130710 (which it ought) then yes, it would have picked up that DTSTAMP correctly just as it would pick up 20130717 for today ...


----------



## Damonc (May 9, 2001)

yeah it works unless theres nothing matching the date, then it just displays a line from the top.. VTIMEZONE..


----------



## JiminSA (Dec 15, 2011)

Just check that $key is greater than 0 (i.e. it has found something) and then do your stuff. If it is zero just check the line again for the presence of your search string (Use strpos)


----------



## JiminSA (Dec 15, 2011)

Sorry - I meant $sub NOT $key (that's the array of results)


----------



## Damonc (May 9, 2001)

Think I may have found a larger problem.. 

The bit in the "$text" is only 1 event from the calendar, I've just gotten a heap of them from the calendar thats actually going to be used and the $keyword =date only returns the last one, not all of them... 

To give you a little insight on what I'm trying to do, friends of mine that keep job bookings in a calendar have asked me if I can have a php iphone friendly page that can load the events from the calendar.. the php can pull the .ics file from the server no worries, its just trying to get it to display only the jobs for that day rather than everything from years gone by.. and display it in a "Human Friendly" format..


----------



## Damonc (May 9, 2001)

it would have been handy (and easier I think) if i could have imported the fields from the .ics file into a MySQL database then just queried it to get the results that I wanted, and then overnight get it to dump and rebuild the database with the latest calendar info..


----------



## JiminSA (Dec 15, 2011)

OK - post the current ics file and highlight what needs to be displayed in a user friendly way and we can take it from there. (ie. show what needs to be displayed to the user for each DTSTART entry - we can then loop through the array and echo out the useful bits ...)


----------



## Damonc (May 9, 2001)

OK heres a portion of the current file (which is huuuge).. but its all the same layout over and over its just the highlighted bits that change.. So it would need to go through the whole file and then find the bits that have todays date in them and echo out the other two fields

BEGIN:VEVENT
DTSTAMP:20130717T062747Z
UID:80462778A326E04EBD831336D01F2A2F41E60A5568B8AF48BD21474C
E7A5256A040000008200E00074C5B7101A82E00800000000D053B277FF82CE01000000000000
000010000000
PRIORITY:5
SUMMARY:Call - Phillip, <- Description goes here sometimes the ics file makes this more than 1 line
X-LABEL:0
CLASSUBLIC
LOCATION:xxxxxxxxxx, <- a 10 digit phone number goes here followed by some other info but only the number is required and its always first
SEQUENCE:0
X-ALARM-TRIGGERT15M
DTSTART;TZID=Australia/Sydney:20130718T140000 <- Echo only if this date matches todays date
DTEND;TZID=Australia/Sydney:20130718T150000
END:VEVENT


----------



## JiminSA (Dec 15, 2011)

Slightly confused here Damon - the DTSTAMP is for the 17th and the DTSTART and DTEND are for the 18th - why is this?


----------



## Damonc (May 9, 2001)

I think the DTSTAMP is when the event is created, however the DTSTART is when the event is scheduled for..


----------



## JiminSA (Dec 15, 2011)

Ok so we search for today's date in a DTSTART line (18th as per Australia not South Africa hehe...) and backtrack to find the previous LOCATION: and SUMMARY: and echo out the pertinent info. Are you confident enough with your php to do this or not?


----------



## Damonc (May 9, 2001)

I could possibly screw around and eventually get it to work haha..

Most of the PHP I've done thus far has been storing info in MySQL, then echoing it back out again, and not much else aside from that.. Just teaching myself as I go along.


----------



## JiminSA (Dec 15, 2011)

Ok mate, no probs - I'll mock something up in a bit and report back, meanwhile give it a bash and see what you come up with.
Hint - $sub contains the first occurrence of the date in $text_array so we will have to subtract x from it to begin examining lines for the data we want (search each line for SUMMARY or LOCATION, using strpos), which we shall "split-out" using explode and the ":" delimiter ... HAVE FUN!


----------



## Damonc (May 9, 2001)

haha.. OK I'll see what I can stumble across


----------



## JiminSA (Dec 15, 2011)

Wouldn't want you to stumble and hurt yourself so I've done a little mock-up (with explanatory notes) and have adjusted your ics array to accommodate time differences between SA and Oz and to simulate multiple line Summary detail handling...

```
<?php

$text = "BEGIN:VEVENT
DTSTAMP:20130717T062747Z
UID:80462778A326E04EBD831336D01F2A2F41E60A5568B8AF48BD21474C
E7A5256A040000008200E00074C5B7101A82E00800000000D053B277FF82CE0100000000000 0
000010000000
PRIORITY:5
SUMMARY:Call - Phillip,
about a job designing websites,
which pays $$$$$$$$$$$!
X-LABEL:0
CLASS:PUBLIC
LOCATION:xxxxxxxxxx,
SEQUENCE:0
X-ALARM-TRIGGER:-PT15M
DTSTART;TZID=Australia/Sydney:20130717T140000
DTEND;TZID=Australia/Sydney:20130717T150000
END:VEVENT";

$text_array = explode( "\n", $text );

echo '';
print_r($text_array);
echo '';

$keyword = date('Ymd');

$key = preg_grep("/{$keyword}/i",$text_array); 	// Find entries for today

foreach($key as $sub=> $value) 					// $sub is the line number -:- $value is the line content
{
	$param = explode(";", $text_array[$sub]); 	// Split off the parameter title for the found line
	if($param[0] == "DTSTART")					// and ensure that it is the entry start line
	{
		$backsub = $sub - 3;					// jump back 3 lines to find the Contact Details
		$backfound = "";
		$backfound = strpos("LOCATION", $text_array[$backsub]);
		if(isset($backfound))					// and make sure it is the correct line
		{
			$location = explode(":", $text_array[$backsub]);	// Split off the Contact details for later printing
		}
		$i = 6;									// jump back 6 lines to find the Job Summary Details
		$found = false;
		while($found == false)
		{
			$backsub = $sub - $i;
			$summaryfound = explode(":", $text_array[$backsub]);	
			if($summaryfound[0] == "SUMMARY")	// Make sure we've found the correct line
			{
				$found = true;					// Yup!
			}
			$i++;								// Nope! Jump back a line till we find it
		}
		$summary = $summaryfound[1];			// Put the first line in a container for subsequent printing
		$no_extra_lines = ($i-1) - $backsub;
		for ($j = 1; $j <= $no_extra_lines; $j++)
		{
			$summary .= $text_array[$backsub+$j];	// add extra lines to the container
		}
		echo "Job Summary: " . $summary . "
";	// and print
		echo "Contact Info: " . $location[1] . "
";
	}	
}

?>
```


----------



## Damonc (May 9, 2001)

Mate that is awesome.. I've changed it to open their full calendar file and its sweet as.. On that contact info line, can we get it to stop the explode at a comma? ","

..If your interested to see what I've developed I can email you a heap of screen shots - can't post you the actual link as its a private server that I VPN into..


----------



## JiminSA (Dec 15, 2011)

Well Damon I'm glad it's sorted
If all you need for the summary is the first line then simply remove (or comment out) the following lines ...

```
$no_extra_lines = ($i-1) - $backsub;
		for ($j = 1; $j <= $no_extra_lines; $j++)
		{
			$summary .= $text_array[$backsub+$j];	// add extra lines to the container
		}
```
 which will stop the addition of any extra lines
A word of advice ... If they change the format of the ics file at any time the code would need to be reviewed
You can always post another thread here at TSG if that happens, but I rather think that your learning curve with php will allow you to DIY by then.
I would be interested to see the results you've obtained, and I'm sure other members would be too. Is there no way you can upload a small selection of your screenshots to this thread? Please take a look at my website (link below) ...


----------



## Damonc (May 9, 2001)

I meant just stop for that line.. or only echo the first 12 characters 

As for screenshots, yep can do.. I'll post some up in a couple of hours when i'm home again


----------



## Damonc (May 9, 2001)

OK So.. here it is.

*What it does/What its for:*
I was asked by friends of mine who own a business if I could create them an sms system for them to notify customers of completed jobs, reminders of upcoming jobs etc. The staff have iPhones connected to the store wifi, so I wanted to utilise that as much as I could.

The system is running on an internal linux server, with a MySQL backend. PHP scripts determine if your on a computer or iphone then direct you to the appropriate site version.. The desktop version is pretty bland, and the main use is the mobiles so I'm only showing off that 

Using an SMS gateway providers API I was able to write scripts to send SMS messages that are preset in the database (there is also an option for writing a custom message), When the customer gets a message it appears from the company name, not a random phone number. There is also an option to check remaining credits on the account.

I wanted to take it one step further and pull jobs from their outlook calendar to display directly in the sms system.. lucky for me their calendar is hosted on a server which can publish the calendar for the sms system to utilise.. This part wouldn't have been possible without the help of JiminSA (a massive thankyou) as this part of PHP was unfamiliar to me. Once completely finished the staff will be able to touch on a phone number that is being pulled from their calendar, and send it one of the preset sms messages (nice and streamlined!)

As you'll see from the screenshots, the mobile site has a swipe menu navigation system, this is still a little buggy as it works once after you've selected an option from it, then you need to reload the page to get it to work again...

I've also added an option to add it on the home screen as a web-app which also has the company logo rather than just a preview of the page so on your iPhones homescreen it actually looks like a proper app.

So time for some screen shots.. I'm using an iPhone simulator to do this as I can only access the page through a VPN connection to the linux server - which my iPhone can't connect to 

Sorry can't show screenshots of the calendar data because it contains client info


----------



## JiminSA (Dec 15, 2011)

Yup I realised that - by removing the code as suggested you'll only get the first line (which includes the comma) - if you want to take the comma out, replace this line

```
$summary = $summaryfound[1];            // Put the first line in a container for subsequent printing
```
with this

```
$bucket = explode(",", $summaryfound[1]);			// Put the first line in a container for subsequent printing
$summary = $bucket[0];
```


----------



## Damonc (May 9, 2001)

OK mate.. One last question.. Related to the same project, but not the script same part that we've already covered haha.

I've got the below code to query a table in the mysql database (thats fine), however when i put the curl stuff in it only processes the first entry.. Thinking I'm missing something somewhere but just want a second set of eyes to have a look..

The curl stuff was actually written by the sms provider, i'm just trying to get it to run for each of the entries in the database to send messages out.. but as I said, it stops after the first.


```
<?php
$host="localhost"; // Host name 
$username=""; // Mysql username 
$password=""; // Mysql password 
$db_name=""; // Database name 
$tbl_name="reminders"; // Table name
$datelist = date('Ymd', strtotime("2 days"));

// Connect to server and select database.
mysql_connect("$host", "$username", "$password")or die("cannot connect"); 
mysql_select_db("$db_name")or die("cannot select DB");

$sql="SELECT * FROM $tbl_name WHERE eventdate = $datelist";
$result=mysql_query($sql);

while($rows=mysql_fetch_array($result)){

echo  $rows['to'];
echo $rows['message'];
    function sendSMS($content) {
        $ch = curl_init('https://www.smsbroadcast.com.au/api-adv.php');
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $output = curl_exec ($ch);
        curl_close ($ch);
        return $output;    
   }

    $username = 'myusername';
    $password = 'mypassword';
    $destination = $rows['to'];
    $source    = 'mysender';
    $text = $rows['message'];
   $ref = '$rows['to']';

    $content =  'username='.rawurlencode($username).
                '&password='.rawurlencode($password).
                '&to='.rawurlencode($destination).
                '&from='.rawurlencode($source).
                '&message='.rawurlencode($text).
                '&ref='.rawurlencode($ref);

    $smsbroadcast_response = sendSMS($content);
    $response_lines = explode("\n", $smsbroadcast_response);

     foreach( $response_lines as $data_line){
        $message_data = "";
        $message_data = explode(':',$data_line);
        if($message_data[0] == "OK"){
            echo "The message was successfully sent. "."\n";
        }elseif( $message_data[0] == "BAD" ){
            echo "The message to ".$message_data[1]." was NOT successful. Reason: ".$message_data[2]."\n";
        }elseif( $message_data[0] == "ERROR" ){
            echo "There was an error with this request. Reason: ".$message_data[1]."\n";
        }
    }

 }

?>
<?php
mysql_close();
?>
```


----------



## JiminSA (Dec 15, 2011)

Are you certain that there should be more than one SMS response per database entry? Because from what you say and what I see of your code, the foreach can only be processing one send of an sms from the database entry at a time. Perhaps you could display your sms(s?) with the following code just before the foreach loop, just to see?

```
echo ''; 
print_r($response_lines); 
echo '';
```


----------



## JiminSA (Dec 15, 2011)

Just an afterthought - I read sometime back that php functions should be placed at the top of your script (yours is placed into your code and I it may be as well to put it at the top, if only for the sake of conformity...)


----------



## Damonc (May 9, 2001)

There should only be one sms per database entry.. adding that extra bit of code shows that its only sending the first entry.


----------



## JiminSA (Dec 15, 2011)

I would check the $content you supply to your curl function - it appears to contain the literals 'myusername' 'mypassword' 'to' 'mysender' are these correct? Shouldn't they contain data from your database entries?


----------



## Damonc (May 9, 2001)

Nope, they are there to be sent to the sms provider for authentication

This segment is their supplied php api code.. 

```
function sendSMS($content) {
        $ch = curl_init('https://www.smsbroadcast.com.au/api-adv.php');
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $content);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $output = curl_exec ($ch);
        curl_close ($ch);
        return $output;    
   }

    $username = 'myusername';
    $password = 'mypassword';
    $destination = $rows['to'];
    $source    = 'mysender';
    $text = $rows['message'];
   $ref = '$rows['to']';

    $content =  'username='.rawurlencode($username).
                '&password='.rawurlencode($password).
                '&to='.rawurlencode($destination).
                '&from='.rawurlencode($source).
                '&message='.rawurlencode($text).
                '&ref='.rawurlencode($ref);

    $smsbroadcast_response = sendSMS($content);
    $response_lines = explode("\n", $smsbroadcast_response);

     foreach( $response_lines as $data_line){
        $message_data = "";
        $message_data = explode(':',$data_line);
        if($message_data[0] == "OK"){
            echo "The message was successfully sent. "."\n";
        }elseif( $message_data[0] == "BAD" ){
            echo "The message to ".$message_data[1]." was NOT successful. Reason: ".$message_data[2]."\n";
        }elseif( $message_data[0] == "ERROR" ){
            echo "There was an error with this request. Reason: ".$message_data[1]."\n";
        }
    }
```


----------



## JiminSA (Dec 15, 2011)

> There should only be one sms per database entry.. adding that extra bit of code shows that its only sending the first entry.


I'm a little confused when you say you are only receiving the first entry, but that there is only one sms message per database entry. Does the sms itself contain more than one entry/line/whatever? If so, are you sure that they are separated by "\n" and not some other character? Best to print $smsbroadcast_response to see how it's constructed, yeh? Or maybe your saying that there is only one database entry for the "Ymd" selection? I'm not sure ...
Did you put your function at the top of the script?


----------



## Damonc (May 9, 2001)

OK so the database table has 3 fiels - the number, the message, the date it is to be sent

Currently there are 4 records in the database (all to my number), with different messages.. When the php script runs, its meant to send a txt message to each of the numbers in the database for that date. It finds the date ok, but will only send the first message on that date.

If i remove all the curl code and change it to echo out the information, it all works.. so theres obviously a problem with how I've got it setup.. and yep I moved the function to the top of the script as you suggested


----------



## JiminSA (Dec 15, 2011)

Well sorry, Damon I'm at a loss as to what is preventing cURL from supplying you with the full amount of available data, However I saw this on my travels and thought you might be interested ...


> In order to use PHP's cURL functions you need to install the » libcurl package. PHP requires that you use libcurl 7.0.2-beta or higher. In PHP 4.2.3, you will need libcurl version 7.9.0 or higher. From PHP 4.3.0, you will need a libcurl version that's 7.9.8 or higher. PHP 5.0.0 requires a libcurl version 7.10.5 or greater.


 ... maybe it's a contributing factor?


----------



## Damonc (May 9, 2001)

Mmmm.. I'll sus it out.. but if your at a loss there isn't much hope for me lol


..I'll have a fiddle with the code and see if i can get it to work.. if so, i'll post the results here for future reference


----------

