Codeigniter disable calendar date after 5 bookings - php

I have calendar whose dates are booked and saved in database. I am trying to pull the bookings from database and show then under corresponding date. Everything is working fine, except the thing, I want the date to be just text instead of link when there are more than 5 events to that date.
I am aware of the calendar template no content cell and content cells. But i want the date to have no link when it has more than 5 events attached to it.
My Model:
public function bookingcalender($year=null,$month=null)
{
if(!$year)
{
$y = date('Y');
}
else
{
$y = $year;
}
if(!$month)
{
$m = date('m');
}
else
{
$m = $month;
}
$this->config = array(
'show_next_prev' => TRUE,
'next_prev_url' => 'http://joshuaflinn.com/CI/booking/show',
'template' => '{table_open}<table class="availability-calendar">{/table_open}
{heading_row_start}<tr class="toolbar">{/heading_row_start}
{heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}
{heading_previous_cell}<th><</th>{/heading_previous_cell}
{heading_next_cell}<th>></th>{/heading_next_cell}
{heading_row_end}</tr>{/heading_row_end}
{week_row_start}<tr>{/week_row_start}
{week_day_cell}<td>{week_day}</td>{/week_day_cell}
{week_row_end}</tr>{/week_row_end}
{cal_row_start}<tr>{/cal_row_start}
{cal_cell_start}<td>{/cal_cell_start}
{cal_cell_start_today}<td>{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-month">{/cal_cell_start_other}
{cal_cell_content}{day}<span class="date-data">{content}</span>{/cal_cell_content}
{cal_cell_content_today}<div class="highlight">{day}</div>{/cal_cell_content_today}
{cal_cell_no_content}{day}{/cal_cell_no_content}
{cal_cell_no_content_today}<div class="highlight">{day}</div>{/cal_cell_no_content_today}
{cal_cell_blank} {/cal_cell_blank}
{cal_cell_other}{day}{/cal_cel_other}
{cal_cell_end}</td>{/cal_cell_end}
{cal_cell_end_today}</td>{/cal_cell_end_today}
{cal_cell_end_other}</td>{/cal_cell_end_other}
{cal_row_end}</tr>{/cal_row_end}
{table_close}</table>{/table_close}'
);
$this->load->library('calendar',$this->config);
$conf_data = $this->get_booked_dates($year,$month);
return $this->calendar->generate($year,$month,$conf_data);
}
public function get_booked_dates($year,$month)
{
$query = $this->db->select('client_name,booking_date')->from('bookings')->like('booking_date',"$year-$month")->get();
$cal_data = array();
foreach($query->result() as $row)
{
$dt = explode("-", $row->booking_date);
$dt = $dt[2];
$k = ($dt >= 10 ? substr($row->booking_date, 8,2) : substr($row->booking_date, 9,1));
if( #$cal_data[$k] == '' )
{
$cal_data[$k] = $row->client_name;
}
else
{
$cal_data[$k] .= ','.$row->client_name;
}
}
return $cal_data;
}

The options you have are limited since Codeigniters Calendar Library only have the two pseudo variables cal_cell_no_content and cal_cell_contentin the template to play with in terms of what content you want to display.
A quick look behind the door reveals that the library uses isset() to determine which of the two pseudo variables to use.
And it calls str_replace {content} before {day} that opens up for a somewhat hacky solution:
public function bookingcalender($year=null,$month=null)
{
if(!$year)
{
$y = date('Y');
}
else
{
$y = $year;
}
if(!$month)
{
$m = date('m');
}
else
{
$m = $month;
}
$this->config = array(
'show_next_prev' => TRUE,
'next_prev_url' => 'http://joshuaflinn.com/CI/booking/show',
'template' => '{table_open}<table class="availability-calendar">{/table_open}
{heading_row_start}<tr class="toolbar">{/heading_row_start}
{heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}
{heading_previous_cell}<th><</th>{/heading_previous_cell}
{heading_next_cell}<th>></th>{/heading_next_cell}
{heading_row_end}</tr>{/heading_row_end}
{week_row_start}<tr>{/week_row_start}
{week_day_cell}<td>{week_day}</td>{/week_day_cell}
{week_row_end}</tr>{/week_row_end}
{cal_row_start}<tr>{/cal_row_start}
{cal_cell_start}<td>{/cal_cell_start}
{cal_cell_start_today}<td>{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-month">{/cal_cell_start_other}
{cal_cell_content}{content}{/cal_cell_content}
{cal_cell_content_today}<div class="highlight">{content}</div>{/cal_cell_content_today}
{cal_cell_no_content}{day}{/cal_cell_no_content}
{cal_cell_no_content_today}<div class="highlight">{day}</div>{/cal_cell_no_content_today}
{cal_cell_blank} {/cal_cell_blank}
{cal_cell_other}{day}{/cal_cel_other}
{cal_cell_end}</td>{/cal_cell_end}
{cal_cell_end_today}</td>{/cal_cell_end_today}
{cal_cell_end_other}</td>{/cal_cell_end_other}
{cal_row_end}</tr>{/cal_row_end}
{table_close}</table>{/table_close}'
);
$this->load->library('calendar',$this->config);
$conf_data = $this->get_booked_dates($year,$month);
return $this->calendar->generate($year,$month,$conf_data);
}
public function get_booked_dates($year,$month)
{
$query = $this->db->select('client_name,booking_date')->from('bookings')->like('booking_date',"$year-$month")->get();
$cal_data = array();
foreach($query->result() as $row)
{
$dt = explode("-", $row->booking_date);
$k = intval($dt[2]); // MAKE INTEGER OF DAY NUMBER
if( #$cal_data[$k] == '' )
{
$cal_data[$k] = $row->client_name;
}
else
{
$cal_data[$k] .= ','.$row->client_name;
}
}
// LOOP THROUGH EACH DAY TO FIND THOSE WITH MORE THAN 5 EVENTS
foreach($cal_data as $key=>$val){
// COUNT THE NUMBER OF COMMAS THAT OCCUR IN STRING
$count = strlen($val) - strlen(str_replace(',','',$val));
if($count > 4){ // IF MORE THAN 4 COMMAS (> 5 EVENTS) THEN NO LINK...
$cal_data[$key] = '{day}<span class="date-data">'.$val.'</span>';
} else { // LINKED DAY
$cal_data[$key] = '{day}<span class="date-data">'.$val.'</span>';
}
}
return $cal_data;
}
Note: that I have changed two rows in the template: {cal_cell_content}{content}{/cal_cell_content} and {cal_cell_content_today}<div class="highlight">{content}</div>{/cal_cell_content_today}
You now only need to set {content} since {day} is specified inside the content also containing the html returned from the query.
Update: I have now tested the solution and it seems to work fine!
You have to manipulate or extend the Calendar library if you need a more flexible solution and if you don't want to mix template html in the content returned from your query.

Related

Calendaring customization [highlighting the current month]

I made a method that writes a view with a calendar table which shows all months of a year using the calendaring class.
Controller:
<?php
class Calendar extends CI_Controller {
public function this_year() {
$data['title'] = 'Calendar: ' . date('Y');
$this->load->library('calendar');
$prefs = array(
'local_time' => 'none',
'start_day' => 'sunday',
'month_type' => 'long',
'day_type' => 'short',
'show_next_prev' => FALSE,
'show_other_days' => TRUE,
'template' => '
{table_open}<table class="table table-condensed">{/table_open}
{heading_row_start}<tr class="info">{/heading_row_start}
{cal_cell_start_today}<td class="today">{/cal_cell_start_today}
{cal_cell_start_other}<td class="other-day">{/cal_cell_start_other}
'
);
$this->load->library('calendar', $prefs);
$data['calendar'] = '<table class="table-calendar"><tr>';
for ($i = 1; $i <= 12; $i++) {
if ($i % 3 == 0) {
$data['calendar'].= "<td>{$this->calendar->generate(date('Y'), $i)}</td>";
$data['calendar'].= '</tr><tr>';
}
else {
$data['calendar'].= "<td>{$this->calendar->generate(date('Y'), $i)}</td>";
}
}
$data['calendar'].= '</tr></table>';
$this->template->load('template/index', __CLASS__ . "/" . __FUNCTION__, $data);
}
}
*On VIEW, just echo '$calendar'
It works as well, and returns this.
But I didn't found a way to highlight only the current month using a template in the calendaring class. I tried to modify the default template but it doesn't work because when I change the class of {heading_title_cell}<th colspan="{colspan}">{heading}</th>{/heading_title_cell}, it modifies all the month's labels like this.
I'm using the default methods (same code) from the basic class tutorial. Any suggestion?
It is possible to extend CI_Calendar to force the method generate() pass his $month variable to the parse_template() method. Then, parse_template($month) will be able to apply an exception while parsing the declared template on {heading_row_start}<tr>{/heading_row_start}:
CI_Calendar::parse_template($month), 483:
if($val == 'heading_row_start'){
if( $month == date('m')){
$this->replacements[$val] = '<tr class="info">';
}
}
else{
$this->replacements[$val] = $match[1];
}

Translating date into spanish Wordpress

I have the followwing site on Wordpress where you can find different schedules with the month in english and i need to change it to spanish:
http://comproautosusados.com/centrolerner2016/horarios/
I tried Loco Translate, trying editing the .pó files and now i'm looking into the theme's php files. I've been able to translate lots of stuff, but i can't translate the months. You can see at the left side of the table that it says "Lunes 28th April" for example. I need to change it to "Lunes 28 Abril".
In the theme's "core"there's this file: timetable.php where this function is found:
public function getDays() {
if (!isset(self::$cache['days'])) {
$days = array();
foreach ($this->get('calendar.period') as $time) {
$object = new VTCore_Wordpress_Objects_Array(array(
'id' => strtolower($time->format('l')),
'timestamp' => $time->getTimeStamp(),
'formatted' => $time->format($this->get('calendar.format')),
'iso' => $time->format('Y-m-d\TH:i:sO'),
'label' => $this->get('days.' . strtolower($time->format('l'))),
));
$days[] = $object;
}
self::$cache['days'] = $days;
}
return self::$cache['days'];
}
There is where the theme generates the date? i don't know what to do.
I have had the same problem, maybe something like this will help you:
<?php
// Get the numeric representation of the current month
$m = date('n');
// Get a full textual representation of the month ( in norwegian )
if ($m==1) { $t = "Januar"; }
if ($m==2) { $t = "Februar"; }
if ($m==3) { $t = "Mars"; }
if ($m==4) { $t = "April"; }
if ($m==5) { $t = "Mai"; }
if ($m==6) { $t = "Juni"; }
if ($m==7) { $t = "Juli"; }
if ($m==8) { $t = "August"; }
if ($m==9) { $t = "September"; }
if ($m==10) { $t = "Oktober"; }
if ($m==11) { $t = "November"; }
if ($m==12) { $t = "Desember"; }
// Display the date
echo date('m').".".$t.".".date('Y'); // returns: 05.Mai.2016
?>

Cakephp pagination custom order

I need to set the pagination order of my register based on field ($results[$key]['Movimento']['status']) created in afterFind callback.
afterFind:
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
if(isset($val['Movimento']['data_vencimento'])) {
$data = $val['Movimento']['data_vencimento'];
$dtVc = strtotime($data);
$dtHj = strtotime(date('Y-m-d'));
$dtVencendo = strtotime("+7 day", $dtHj);
if ($dtVc < $dtHj) {
$results[$key]['Movimento']['status'] = 'vencido';
} elseif ($dtVc <= $dtVencendo) {
$results[$key]['Movimento']['status'] = 'vc15dias';
} else {
$results[$key]['Movimento']['status'] = 'aberto';
}
}
if(isset($val['Movimento']['data_pagamento'])) {
$results[$key]['Movimento']['status'] = 'quitado';
}
}
return $results;
Pagination:
$options = array(
...
'order' => array('Movimento.status' => 'ASC')
);
$this->controller->paginate = $options;
$movimentos = $this->controller->paginate('Movimento');
I know this does not work because the field is created after the paginator call.
Can I make it work?
as I understand, you want to sort by data_pagamento and than by data_vencimento (has it the mysql-type date?)
so you don't need your afterFind-function for ordering, simply use:
'order' => array(
'Movimento.data_pagamento DESC',//first all rows with not-empty data_pagamento
'Movimento.data_vencimento DESC',// first all dates in the furthest future
)

CodeIgniter's Calendar Doesn't Show Some Entries From Database Table

I used CodeIgniter's calendar library to populate data from a database table but apparently it has following issues:
No more than 1 reocrd is shown
Entries below the day 9 of the month are not shown while everything else is working
Why would this happen?
Model:
class reminders_model extends CI_Model {
var $conf;
function reminders_model() {
parent::__construct();
$this->conf = array(
'start_day' => 'monday',
'month_type' => 'long',
'day_type' => 'long'
);
$this->conf['template'] = '
{table_open}
<table class="calendar">
{/table_open}
{week_day_cell}
<th class="day_header">{week_day}</th>
{/week_day_cell}
{cal_row_start}<tr class="days">{/cal_row_start}
{cal_cell_start}<td class="day">{/cal_cell_start}
{cal_cell_content}
<span class="day_listing">{day}</span> • {content} {/cal_cell_content}
{cal_cell_content_today}
<div class="today"><span class="day_listing">{day}</span>• {content}</div>{/cal_cell_content_today}
{cal_cell_no_content}
<span class="day_listing">{day}</span> {/cal_cell_no_content}
{cal_cell_no_content_today}
<div class="today"><span class="day_listing">{day}</span></div>{/cal_cell_no_content_today}
';
}
function get_calendar_data($year, $month) {
$query = $this->db->select('date, reason')->from('reminders')->like('date', "$year-$month", 'after')->get();
$cal_data = array();
foreach ($query->result() as $row) {
$cal_data[substr($row->date, 8, 2)] = $row->reason;
}
return $cal_data;
}
function generate($year, $month) {
$this->load->library('calendar', $this->conf);
$cal_data = $this->get_calendar_data($year, $month);
return $this->calendar->generate($year, $month, $cal_data);
}
Controller:
<?php
class reminders extends CI_Controller {
function index($year = null, $month = null) {
if (!$year) {
$year = date('Y');
}
if (!$month) {
$month = date('m');
}
$this->load->model('/summary/reminders_model');
if ($day = $this->input->post('day')) {
$this->reminders_model->add_calendar_data(
"$year-$month-$day",
$this->input->post('reason')
);
}
$data['calendar'] = $this->reminders_model->generate($year, $month);
$this->load->view('summary/reminders_view', $data);
}
View:
<?php echo $calendar; ?>
In order to put more than one item into a day, say the 15th you'll have to create a multi-dimensional array to get multiple appointments on it. For instance.
function get_calendar_data($year, $month) {
$query = $this->db->select('date, reason')->from('reminders')->like('date', "$year-$month", 'after')->get();
$cal_data = array();
foreach ($query->result() as $row) {
$day = date('j',$row->date);
$cal_data[$day][] = $row->reason;
}
return $cal_data;
}
As for the reason your only getting 9, I'm guessing it has to do with your substr()

How to extend or modify Codeigniter calendar to handle multi-day events and multiple events per day

I'd hate to reinvent the wheel on this one if it's out there somewhere, but has anyone extended or modified the codigniter calendar to handle multi-day events and multiple events per day or is it there a module available somewhere?
Multiple events for one day is actually very easy. It just takes changing the calendar template and here is an example from some of my code.
public function print_calendar($year = 0, $month = 0)
{
$prefs = array (
'show_next_prev' => FALSE,
'next_prev_url' => site_url('events/print_calendar'),
'day_type' => 'long',
'template' => '
{heading_row_start}{/heading_row_start}
{heading_previous_cell}{/heading_previous_cell}
{heading_title_cell}<h1>{heading}</h1>{/heading_title_cell}
{heading_next_cell}{/heading_next_cell}
{heading_row_end}{/heading_row_end}
{table_open}<table border="0" cellpadding="0" cellspacing="0">{/table_open}
{week_row_start}<tr>{/week_row_start}
{week_day_cell}<th bgcolor="#999999">{week_day}</th>{/week_day_cell}
{week_row_end}</tr>{/week_row_end}
{cal_row_start}<tr>{/cal_row_start}
{cal_cell_start}<td background="'.s3_path('images/print_cal_cell.jpg').'">{/cal_cell_start}
{cal_cell_content}<span class="cal_day">{day}</span>{content}{/cal_cell_content}
{cal_cell_content_today}<span class="cal_day">{day}</span>{/cal_cell_content_today}
{cal_cell_no_content}<span class="cal_day">{day}</span>{/cal_cell_no_content}
{cal_cell_no_content_today}<span class="cal_day">{day}</span>{/cal_cell_no_content_today}
{cal_cell_blank} {/cal_cell_blank}
{cal_cell_end}</td>{/cal_cell_end}
{cal_row_end}</tr>{/cal_row_end}
{table_close}</table>{/table_close}
'
);
$this->load->library('calendar', $prefs);
$year = ($year == 0) ? date('Y') : $year;
$month = ($month == 0) ? date('n') : $month;
$start = strtotime('1-'.$month.'-'.$year);
$events = $this->events_model->get_by_date($start, strtotime('+1 month', $start));
$this->template->set_layout('');
if ($events)
{
foreach ($events as $key => $event)
{
$day = date('j', $event['showing_start_time']);
$vars[$day] = $this->template->build('events/calendar/cal_item', $event, TRUE);
}
}
$vars['content'] = $this->calendar->generate($year, $month, $vars);
$this->load->view('calendar/cal_layout', $vars);
}
Hopefully that code is clear and can give you a good starting point. What I normally do if they span multiple days just include the item on each day.
This can be easily modified in the file system/libraries/Calendar.php with the following addition of code. I know that editing any system file is considered taboo, but this helped me out in my application a ton. Take note of the foreach() loop in the commented section that says //If more than one event on the same day. This is the code that needs to be added to the Calendar.php library file. This resource can be futher elaborated on at the following link.
http://codeigniter.com/forums/viewthread/196998/
Calendar.php modified code:
if (isset($data[$day]))
{
// Cells with content
$temp = ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_content_today'] : $this->temp['cal_cell_content'];
// If more than one event on the same day
if (is_array($data[$day]))
{
$several_events = '';
foreach ($data[$day] as $key => $value)
{
$several_events .= '<li id="'.$key.'">'.$value.'</li>';
}
$out .= str_replace('{day}', $day, str_replace('{content}', $several_events, $temp));
}
// One event per day
else
{
$out .= str_replace('{day}', $day, str_replace('{content}', $data[$day], $temp));
}
}
else
{
// Cells with no content
$temp = ($is_current_month == TRUE AND $day == $cur_day) ? $this->temp['cal_cell_no_content_today'] : $this->temp['cal_cell_no_content'];
$out .= str_replace('{day}', $day, $temp);
}
}
else
{
// Blank cells
$out .= $this->temp['cal_cell_blank'];
}
Keep in mind that I've shown more than just the edited code above to help you locate it within Calendar.php. I hope this helps!

Categories