diff --git a/public/class-bread-content-generator.php b/public/class-bread-content-generator.php
index d4b3aba..71d722a 100644
--- a/public/class-bread-content-generator.php
+++ b/public/class-bread-content-generator.php
@@ -15,15 +15,50 @@
*/
class Bread_ContentGenerator
{
+ /**
+ * Converts HTML to PDF.
+ *
+ * @var Mpdf
+ */
private Mpdf $mpdf;
+ /**
+ * The configuration of the meeting list.
+ *
+ * @var array
+ */
private array $options;
+ /**
+ * The meetings in the meeting list.
+ *
+ * @var array
+ */
private array $result_meetings;
+ /**
+ * The standard shortcodes, not including fields in the array representing the meeting. Used on front and last pages, etc.
+ *
+ * @var array
+ */
private array $shortcodes;
private int $meeting_count;
private $target_timezone;
+ /**
+ * The format indicating accessibility gets special treatment (graphic symbol). The format is identified by the NAWS format associated with it.
+ *
+ * @var array
+ */
private array $wheelchair_format;
+ /**
+ * Convenient API for dealing with formats.
+ *
+ * @var Bread_FormatsManager
+ */
private Bread_FormatsManager $formatsManager;
- private array $legacy_synonyms = array (
+ /**
+ * Usually, the key fieled in the array representing the meeting is used to insert a value into a template. But we also have these convenience names.
+ *
+ * @var array
+ */
+ private array $legacy_synonyms = array(
'borough' => 'location_city_subsection',
'time' => 'start_time',
'state' => 'location_province',
@@ -44,7 +79,7 @@ class Bread_ContentGenerator
* The constuctor sets things up so that we are ready to generate.
*
* @param Mpdf $mpdf The object that converts HTML to PDF.
- * @param array $options
+ * @param array $options The configuration of the meeting list.
* @param array $result_meetings The meetings to be included in the list.
* @param Bread_FormatsManager $formatsManager
*/
@@ -60,7 +95,7 @@ function __construct(object $mpdf, array $options, array $result_meetings, Bread
$this->meeting_count = count($result_meetings);
$this->wheelchair_format = $formatsManager->getFormatFromField($this->options['weekday_language'], 'world_id', 'WCHR');
$this->shortcodes = array(
- '
' => '',
+ '' => '',
'
[page_break]
' => '',
'[page_break]
' => '',
'[page_break]' => '',
@@ -83,25 +118,24 @@ function __construct(object $mpdf, array $options, array $result_meetings, Bread
"[service_body_4]" => strtoupper($this->options['service_body_4']),
"[service_body_5]" => strtoupper($this->options['service_body_5']),
- );
+ );
$this->shortcodes = apply_filters("Bread_Section_Shortcodes", $this->shortcodes, Bread_Bmlt::get_areas(), $formatsManager->getFormatsUsed());
if ($this->options['page_fold'] == 'half' || $this->options['page_fold'] == 'full') {
- $this->mpdf->DefHTMLFooterByName('MyFooter', ''.$this->options['nonmeeting_footer'].'
');
- $this->mpdf->DefHTMLFooterByName('_default', ''.$this->options['nonmeeting_footer'].'
');
- $this->mpdf->DefHTMLFooterByName('Meeting1Footer', ''.$this->options['meeting1_footer'].'
');
- $this->mpdf->DefHTMLFooterByName('Meeting2Footer', ''.$this->options['meeting2_footer'].'
');
- }
- if (isset($this->options['pageheader_content'])) {
- $data = $this->options['pageheader_content'];
- $this->standard_shortcode_replacement($data, 'pageheader', $this->shortcodes);
+ $this->mpdf->DefHTMLFooterByName('MyFooter', '' . $this->options['nonmeeting_footer'] . '
');
+ $this->mpdf->DefHTMLFooterByName('_default', '' . $this->options['nonmeeting_footer'] . '
');
+ $this->mpdf->DefHTMLFooterByName('Meeting1Footer', '' . $this->options['meeting1_footer'] . '
');
+ $this->mpdf->DefHTMLFooterByName('Meeting2Footer', '' . $this->options['meeting2_footer'] . '
');
+ }
+ if (!empty($this->options['pageheader_content'])) {
+ $data = $this->standard_shortcode_replacement('pageheader_content');
$header_style = "vertical-align: top; text-align: center; font-weight: bold;margin-top:3px;margin-bottom:3px;";
- $header_style .= "color:".$this->options['pageheader_textcolor'].";";
- $header_style .= "background-color:".$this->options['pageheader_backgroundcolor'].";";
- $header_style .= "font-size:".$this->options['pageheader_fontsize']."pt;";
- $header_style .= "line-height:".$this->options['content_line_height'].";";
+ $header_style .= "color:" . $this->options['pageheader_textcolor'] . ";";
+ $header_style .= "background-color:" . $this->options['pageheader_backgroundcolor'] . ";";
+ $header_style .= "font-size:" . $this->options['pageheader_fontsize'] . "pt;";
+ $header_style .= "line-height:" . $this->options['content_line_height'] . ";";
$this->mpdf->SetHTMLHeader(
- ''.$data.'
',
+ '' . $data . '
',
'O'
);
}
@@ -110,14 +144,20 @@ function __construct(object $mpdf, array $options, array $result_meetings, Bread
$this->mpdf->showWatermarkImage = true;
}
}
- public function generate($num_columns)
+ /**
+ * Generates the contents of the meeting list.
+ *
+ * @param int $num_columns The number of columns in the meeting list.
+ * @return void
+ */
+ public function generate(int $num_columns): void
{
- require_once __DIR__.'/class-bread-heading-manager.php';
+ require_once __DIR__ . '/class-bread-heading-manager.php';
$this->mpdf->SetColumns($num_columns, '', $this->options['column_gap']);
if ($this->options['page_fold'] == 'half' || $this->options['page_fold'] == 'full') {
$this->write_front_page();
}
- $this->mpdf->WriteHTML('td{font-size: '.$this->options['content_font_size']."pt;line-height:".$this->options['content_line_height'].';background-color:#ffffff00;}', 1);
+ $this->mpdf->WriteHTML('td{font-size: ' . $this->options['content_font_size'] . "pt;line-height:" . $this->options['content_line_height'] . ';background-color:#ffffff00;}', 1);
$this->mpdf->SetDefaultBodyCSS('font-size', $this->options['content_font_size'] . 'pt');
$this->mpdf->SetDefaultBodyCSS('line-height', $this->options['content_line_height']);
$this->mpdf->SetDefaultBodyCSS('background-color', '#ffffff00');
@@ -128,8 +168,8 @@ public function generate($num_columns)
foreach ($this->result_meetings as &$value) {
$value = $this->enhance_meeting($value, $lang);
}
- $headingManager = new Bread_Heading_Manager($this->options, $this->result_meetings, $lang, $this->options['include_asm']==0 ? -1 : 0);
- $this->writeMeetings($this->options['meeting_template_content'], $headingManager);
+ $meetingslistStructure = new Bread_Meetingslist_Structure($this->options, $this->result_meetings, $lang, $this->options['include_asm'] == 0 ? -1 : 0);
+ $this->writeMeetings($this->options['meeting_template_content'], $meetingslistStructure);
if ($this->options['page_fold'] !== 'half' && $this->options['page_fold'] !== 'full') {
$this->write_custom_section();
@@ -141,12 +181,24 @@ public function generate($num_columns)
}
}
}
- function writeHTML($str)
+ /**
+ * Writes a HTML string to th PDF.
+ *
+ * @param string $str The string to be written.
+ * @return void
+ */
+ private function writeHTML(string $str): void
{
//$str = htmlentities($str);
@$this->mpdf->WriteHTML(wpautop(stripslashes($str)));
}
- function standard_shortcode_replacement(&$data, $page)
+ /**
+ * Replace the shortcodes with the standard values (not meeting dependent).
+ *
+ * @param string $page The text containing the shortcodes.
+ * @return string
+ */
+ private function standard_shortcode_replacement(string $page): string
{
$search_strings = array();
$replacements = array();
@@ -157,21 +209,29 @@ function standard_shortcode_replacement(&$data, $page)
$search_strings[] = '[meeting_count]';
$replacements[] = $this->meeting_count;
- $data = $this->options[$page.'_content'];
- $data = $this->locale_month_replacement($data, 'lower', "LLLL");
- $data = $this->locale_month_replacement($data, 'upper', "LLLL");
+ $data = $this->options[$page];
+ $data = $this->locale_month_replacement($data, 'lower');
+ $data = $this->locale_month_replacement($data, 'upper');
$data = str_replace($search_strings, $replacements, $data);
$this->replace_format_shortcodes($data, $page);
$data = str_replace("[date]", strtoupper(date("F Y")), $data);
if ($this->target_timezone) {
$data = str_replace('[timezone]', $this->target_timezone->getName(), $data);
}
+ return $data;
}
- function locale_month_replacement($data, $case, $sym)
+ /**
+ * Replace [month] shortcodes with the locale-specific name of the month.
+ *
+ * @param string $data The text containing the shortcode.
+ * @param string $case 'upper' or 'lower'
+ * @return string The text with the shortcode replaced by the value.
+ */
+ private function locale_month_replacement(string $data, string $case): string
{
- $strpos = strpos($data, "[month_$case"."_");
+ $strpos = strpos($data, "[month_$case" . "_");
if ($strpos !== false) {
- $locLang = substr($data, $strpos+13, 2);
+ $locLang = substr($data, $strpos + 13, 2);
if (!isset($this->translate[$locLang])) {
$locLang = 'en';
}
@@ -180,16 +240,22 @@ function locale_month_replacement($data, $case, $sym)
IntlDateFormatter::FULL,
IntlDateFormatter::FULL
);
- $fmt->setPattern($sym);
+ $fmt->setPattern('LLLL');
$month = ucfirst(mb_convert_encoding($fmt->format(time()), 'UTF-8', 'ISO-8859-1'));
- if ($case=='upper') {
- $month = mb_strtoupper($month, 'UTF-8');
+ if ($case == 'upper') {
+ $month = mb_strtoupper($month, 'UTF-8');
}
return substr_replace($data, $month, $strpos, 16);
}
return $data;
}
- function orderByWeekdayStart(&$result_meetings)
+ /**
+ * Order the meetings so that the list starts on the day of the week selected in the configuation.
+ *
+ * @param array $result_meetings The meetings
+ * @return array The meetings.
+ */
+ private function orderByWeekdayStart(array &$result_meetings): array
{
$days = array_column($result_meetings, 'weekday_tinyint');
$today_str = $this->options['weekday_start'];
@@ -198,38 +264,49 @@ function orderByWeekdayStart(&$result_meetings)
array_splice($result_meetings, 0)
);
}
- function write_front_page()
+ /**
+ * Generate the front page.
+ *
+ * @return void
+ */
+ private function write_front_page()
{
-
- $this->mpdf->WriteHTML('td{font-size: '.$this->options['front_page_font_size']."pt;line-height:".$this->options['front_page_line_height'].';}', 1);
+ $this->mpdf->WriteHTML('td{font-size: ' . $this->options['front_page_font_size'] . "pt;line-height:" . $this->options['front_page_line_height'] . ';}', 1);
$this->mpdf->SetDefaultBodyCSS('line-height', $this->options['front_page_line_height']);
$this->mpdf->SetDefaultBodyCSS('font-size', $this->options['front_page_font_size'] . 'pt');
$this->mpdf->SetDefaultBodyCSS('background-color', '#ffffff00');
$this->options['front_page_content'] = wp_unslash($this->options['front_page_content']);
- $this->standard_shortcode_replacement($this->options['front_page_content'], 'front_page');
-
+ $data = $this->standard_shortcode_replacement('front_page_content');
$querystring_custom_items = array();
preg_match_all('/(\[querystring_custom_\d+\])/', $this->options['front_page_content'], $querystring_custom_items);
foreach ($querystring_custom_items[0] as $querystring_custom_item) {
$mod_qs_ci = str_replace("]", "", str_replace("[", "", $querystring_custom_item));
- $this->options['front_page_content'] = str_replace($querystring_custom_item, (isset($_GET[$mod_qs_ci]) ? $_GET[$mod_qs_ci] : "NOT SET"), $this->options['front_page_content']);
+ $data = str_replace($querystring_custom_item, (isset($_GET[$mod_qs_ci]) ? $_GET[$mod_qs_ci] : "NOT SET"), $data);
}
- $this->writeHTMLwithServiceMeetings($this->options['front_page_content'], 'front_page');
+ $this->writeHTMLwithServiceMeetings($data);
$this->mpdf->showWatermarkImage = false;
}
-
- function write_last_page()
+ /**
+ * Generate the last page.
+ *
+ * @return void
+ */
+ private function write_last_page()
{
- $this->mpdf->WriteHTML('td{font-size: '.$this->options['last_page_font_size']."pt;line-height:".$this->options['last_page_line_height'].';}', 1);
+ $this->mpdf->WriteHTML('td{font-size: ' . $this->options['last_page_font_size'] . "pt;line-height:" . $this->options['last_page_line_height'] . ';}', 1);
$this->mpdf->SetDefaultBodyCSS('font-size', $this->options['last_page_font_size'] . 'pt');
$this->mpdf->SetDefaultBodyCSS('line-height', $this->options['last_page_line_height']);
$this->mpdf->SetDefaultBodyCSS('background-color', '#ffffff00');
- $this->standard_shortcode_replacement($this->options['last_page_content'], 'last_page');
- $this->writeHTMLwithServiceMeetings($this->options['last_page_content'], 'last_page');
+ $data = $this->standard_shortcode_replacement('last_page_content');
+ $this->writeHTMLwithServiceMeetings($data);
}
-
- function write_custom_section()
+ /**
+ * Generate the custom section.
+ *
+ * @return void
+ */
+ private function write_custom_section()
{
$this->mpdf->SetHTMLHeader();
if (isset($this->options['pageheader_content']) && trim($this->options['pageheader_content'])) {
@@ -238,14 +315,18 @@ function write_custom_section()
$this->mpdf->SetDefaultBodyCSS('line-height', $this->options['custom_section_line_height']);
$this->mpdf->SetDefaultBodyCSS('font-size', $this->options['custom_section_font_size'] . 'pt');
$this->mpdf->SetDefaultBodyCSS('background-color', '#ffffff00');
- $this->standard_shortcode_replacement($this->options['custom_section_content'], 'custom_section');
- $this->mpdf->WriteHTML('td{font-size: '.$this->options['custom_section_font_size']."pt;line-height:".$this->options['custom_section_line_height'].';}', 1);
- $this->writeHTMLwithServiceMeetings($this->options['custom_section_content'], 'custom_section');
+ $data = $this->standard_shortcode_replacement('custom_section_content');
+ $this->mpdf->WriteHTML('td{font-size: ' . $this->options['custom_section_font_size'] . "pt;line-height:" . $this->options['custom_section_line_height'] . ';}', 1);
+ $this->writeHTMLwithServiceMeetings($data);
}
- // include_asm = 0 - let everything through
- // 1 - only meetings with asm format
- // -1 - only meetings without asm format
- function writeMeetings($template, Bread_Heading_Manager $headerManager)
+ /**
+ * Generate the meeting list itself, using the specified template and the meetings as structed by the heading manager.
+ *
+ * @param string $template
+ * @param Bread_Meetingslist_Structure $meetingslistStructure
+ * @return void
+ */
+ private function writeMeetings(string $template, Bread_Meetingslist_Structure $meetingslistStructure): void
{
$template = wpautop(stripslashes($template));
$template = preg_replace('/[[:^print:]]/', ' ', $template);
@@ -260,30 +341,36 @@ function writeMeetings($template, Bread_Heading_Manager $headerManager)
* to a test PDF, see how big it is, and check if it will fit.
*/
$test_pages = deep_copy($this->mpdf);
- while ($subheadings = $headerManager->iterateMainHeading()) {
- while ($meetings = $headerManager->iterateSubHeading($subheadings)) {
- while ($meeting_value = $headerManager->iterateMeetings($meetings)) {
- $header = $headerManager->calculateHeading();
+ while ($subheadings = $meetingslistStructure->iterateMainHeading()) {
+ while ($meetings = $meetingslistStructure->iterateSubHeading($subheadings)) {
+ while ($meeting_value = $meetingslistStructure->iterateMeetings($meetings)) {
+ $header = $meetingslistStructure->calculateHeading();
$data = $this->write_single_meeting(
$meeting_value,
$template,
- $analysedTemplate,
- $meeting_value['area_name']
+ $analysedTemplate
);
$this->writeBreak($test_pages);
$y_startpos = $test_pages->y;
- @$test_pages->WriteHTML($header.$data);
+ @$test_pages->WriteHTML($header . $data);
$y_diff = $test_pages->y - $y_startpos;
if ($y_diff >= $this->mpdf->h - ($this->mpdf->y + $this->mpdf->bMargin + 5) - $this->mpdf->kwt_height) {
$this->writeBreak($this->mpdf);
- $header = $headerManager->calculateContHeader();
+ $header = $meetingslistStructure->calculateContHeader();
}
- $this->WriteHTML($header.$data);
+ $this->WriteHTML($header . $data);
}
}
}
}
- function writeBreak($mpdf)
+ /**
+ * Write a break between meetings, so that the meeting does not get broken up in the printout.
+ * In booklets, a page break. In fliers, a column break.
+ *
+ * @param Mpdf $mpdf
+ * @return void
+ */
+ private function writeBreak(Mpdf $mpdf)
{
if ($this->options['page_fold'] === 'half' || $this->options['page_fold'] === 'full') {
$mpdf->WriteHTML("");
@@ -291,25 +378,31 @@ function writeBreak($mpdf)
$mpdf->WriteHTML("");
}
}
-
- function analyseTemplate($template)
+ /**
+ * Break up the template into chunks, so that it can be efficiently processed/ filled with values from the meeting.
+ *
+ * @param string $template
+ * @return array chunks to be used by the write_single_meeting method.
+ */
+ private function analyseTemplate(string $template): array
{
$arr = preg_split('/\W+/', $template, 0, PREG_SPLIT_OFFSET_CAPTURE);
$arr = array_reverse($arr, true);
$ret = array();
foreach ($arr as $item) {
- if (strlen($item[0])<3) {
+ if (strlen($item[0]) < 3) {
continue;
}
$htmlTags = array('table', 'tbody', 'strong', 'left', 'right', 'top', 'bottom', 'center', 'align', 'font', 'size', 'text', 'style', 'family', 'vertical', 'color', 'QRCode');
if (in_array($item[0], $htmlTags)) {
continue;
}
- if ($item[1]>0 && $template[$item[1]-1]=='['
- && $template[$item[1]+strlen($item[0])]==']') {
- $item[0] = '['.$item[0].']';
- $item[1] = $item[1] - 1;
- $item[2] = true;
+ if ($item[1] > 0 && $template[$item[1] - 1] == '['
+ && $template[$item[1] + strlen($item[0])] == ']'
+ ) {
+ $item[0] = '[' . $item[0] . ']';
+ $item[1] = $item[1] - 1;
+ $item[2] = true;
} else {
$item[2] = false;
}
@@ -317,18 +410,25 @@ function analyseTemplate($template)
}
return $ret;
}
- function enhance_meeting(&$meeting_value, $lang)
+ /**
+ * Enhance the meeting fields (in place) with calculated values.
+ *
+ * @param array $meeting_value the raw meeting values, as returned from the BMLT root server.
+ * @param string $lang The language used when generating format descriptions, etc.
+ * @return void
+ */
+ private function enhance_meeting(&$meeting_value, $lang)
{
$duration = explode(':', $meeting_value['duration_time']);
- $minutes = intval($duration[0])*60 + intval($duration[1]) + intval($duration[2]);
+ $minutes = intval($duration[0]) * 60 + intval($duration[1]) + intval($duration[2]);
$meeting_value['duration_m'] = $minutes;
- $meeting_value['duration_h'] = rtrim(rtrim(number_format($minutes/60, 2), 0), '.');
+ $meeting_value['duration_h'] = rtrim(rtrim(number_format($minutes / 60, 2), 0), '.');
$space = ' ';
if ($this->options['remove_space'] == 1) {
$space = '';
}
if ($this->options['time_clock'] == null || $this->options['time_clock'] == '12' || $this->options['time_option'] == '') {
- $time_format = "g:i".$space."A";
+ $time_format = "g:i" . $space . "A";
} elseif ($this->options['time_clock'] == '24fr') {
$time_format = "H\hi";
} else {
@@ -343,10 +443,10 @@ function enhance_meeting(&$meeting_value, $lang)
$addtime = '+ ' . $minutes . ' minutes';
$end_time = date($time_format, strtotime($meeting_value['start_time'] . ' ' . $addtime));
$meeting_value['start_time'] = date($time_format, strtotime($meeting_value['start_time']));
- if ($lang=='fa') {
- $meeting_value['start_time'] = $this->toPersianNum($end_time).$space.'-'.$space.$this->toPersianNum($meeting_value['start_time']);
+ if ($lang == 'fa') {
+ $meeting_value['start_time'] = $this->toPersianNum($end_time) . $space . '-' . $space . $this->toPersianNum($meeting_value['start_time']);
} else {
- $meeting_value['start_time'] = $meeting_value['start_time'].$space.'-'.$space.$end_time;
+ $meeting_value['start_time'] = $meeting_value['start_time'] . $space . '-' . $space . $end_time;
}
} elseif ($this->options['time_option'] == '3') {
$time_array = array("1:00", "2:00", "3:00", "4:00", "5:00", "6:00", "7:00", "8:00", "9:00", "10:00", "11:00", "12:00");
@@ -365,11 +465,11 @@ function enhance_meeting(&$meeting_value, $lang)
if ($temp_end_time == '12:00PM') {
$end_time = 'NOON';
} elseif (in_array($temp_end_time_2, $time_array)) {
- $end_time = date("g".$space."A", strtotime($temp_end_time));
+ $end_time = date("g" . $space . "A", strtotime($temp_end_time));
} else {
- $end_time = date("g:i".$space."A", strtotime($temp_end_time));
+ $end_time = date("g:i" . $space . "A", strtotime($temp_end_time));
}
- $meeting_value['start_time'] = $start_time.$space.'-'.$space.$end_time;
+ $meeting_value['start_time'] = $start_time . $space . '-' . $space . $end_time;
}
$meeting_value['day_abbr'] = Bread::getday($meeting_value['weekday_tinyint'], true, $lang);
@@ -382,13 +482,21 @@ function enhance_meeting(&$meeting_value, $lang)
if (!is_null($this->wheelchair_format)) {
$fmts = explode(',', $meeting_value['format_shared_id_list']);
if (in_array($this->wheelchair_format['id'], $fmts)) {
- $meeting_value['wheelchair'] = '';
+ $meeting_value['wheelchair'] = '';
}
}
// Extensions.
return apply_filters("Bread_Enrich_Meeting_Data", $meeting_value, $this->formatsManager->getHashedFormats($lang));
}
- function write_single_meeting($meeting_value, $template, $analysedTemplate, $area_name)
+ /**
+ * Write a single meeting to the PDF
+ *
+ * @param array $meeting_value The meeting data.
+ * @param string $template
+ * @param array $analysedTemplate
+ * @return void
+ */
+ private function write_single_meeting(array $meeting_value, string $template, array $analysedTemplate)
{
$data = $template;
$namedValues = array();
@@ -401,7 +509,7 @@ function write_single_meeting($meeting_value, $template, $analysedTemplate, $are
foreach ($analysedTemplate as $item) {
$name = $item[0];
if ($item[2]) {
- $name = substr($name, 1, strlen($name)-2);
+ $name = substr($name, 1, strlen($name) - 2);
}
if (isset($namedValues[$name])) {
$data = substr_replace($data, $namedValues[$name], $item[1], strlen($item[0]));
@@ -410,11 +518,11 @@ function write_single_meeting($meeting_value, $template, $analysedTemplate, $are
$qr_pos = strpos($data, "[QRCode");
if ($qr_pos) {
$qr_end = strpos($data, ']', $qr_pos);
- $data = substr($data, 0, $qr_pos).
- ''.
- substr($data, $qr_end+1);
+ $data = substr($data, 0, $qr_pos) .
+ '' .
+ substr($data, $qr_end + 1);
}
$search_strings = array();
$replacements = array();
@@ -454,10 +562,20 @@ function write_single_meeting($meeting_value, $template, $analysedTemplate, $are
$data = str_replace($search_strings, $replacements, $data);
return $data;
}
- function writeHTMLwithServiceMeetings($data, $page)
+ /**
+ * Generate the PDF of templates that also contain "additional lists" and format tables.
+ *
+ * @param string $data The template.
+ * @return void
+ */
+ private function writeHTMLwithServiceMeetings(string $data)
{
- $strs = array('[service_meetings]
','[service_meetings]',
- '[additional_meetings]
','[additional_meetings]');
+ $strs = array(
+ '[service_meetings]
',
+ '[service_meetings]',
+ '[additional_meetings]
',
+ '[additional_meetings]'
+ );
foreach ($strs as $str) {
$pos = strpos($data, $str);
@@ -468,17 +586,17 @@ function writeHTMLwithServiceMeetings($data, $page)
$this->WriteHTML('');
}
$this->WriteHTML(substr($data, 0, $pos));
- $this->write_service_meetings($this->options[$page.'_font_size'], $this->options[$page.'_line_height']);
+ $this->write_service_meetings();
if ($this->options['page_fold'] == 'half' || $this->options['page_fold'] == 'full') {
$this->WriteHTML('');
}
- $this->WriteHTML(substr($data, $pos+strlen($str)));
+ $this->WriteHTML(substr($data, $pos + strlen($str)));
return;
}
$this->WriteHTML($data);
}
- function replace_format_shortcodes(&$data, $page_name)
+ private function replace_format_shortcodes(&$data, $page_name)
{
$lang = $this->options['weekday_language'];
$this->shortcode_formats('[format_codes_used_basic]', false, $lang, false, $page_name, $data);
@@ -489,25 +607,31 @@ function replace_format_shortcodes(&$data, $page_name)
$this->shortcode_formats('[format_codes_all_basic]', false, $lang, true, $page_name, $data);
$this->shortcode_formats('[format_codes_all_detailed]', true, $lang, true, $page_name, $data);
}
- function shortcode_formats($shortcode, $detailed, $lang, $isAll, $page, &$str)
+ private function shortcode_formats($shortcode, $detailed, $lang, $isAll, $page, &$str)
{
$pos = strpos($str, $shortcode);
- if ($pos==false) {
+ if ($pos == false) {
return;
}
$value = '';
if ($detailed) {
- $value = $this->formatsManager->write_detailed_formats($lang, $isAll, $this->options[$page.'_line_height'], $this->options[$page.'_font_size']."pt");
+ $value = $this->formatsManager->write_detailed_formats($lang, $isAll, $this->options[$page . '_line_height'], $this->options[$page . '_font_size'] . "pt");
} else {
- $value = $this->formatsManager->write_formats($lang, $isAll, $this->options[$page.'_line_height'], $this->options[$page.'_font_size']."pt");
+ $value = $this->formatsManager->write_formats($lang, $isAll, $this->options[$page . '_line_height'], $this->options[$page . '_font_size'] . "pt");
}
- $str = substr($str, 0, $pos).$value.substr($str, $pos+strlen($shortcode));
+ $str = substr($str, 0, $pos) . $value . substr($str, $pos + strlen($shortcode));
}
- function asm_required($data)
+ /**
+ * Does a template contain an "additional meeting list"?
+ *
+ * @param string $data
+ * @return void
+ */
+ private function asm_required(string $data): bool
{
return strpos($data, '[service_meetings]') || strpos($data, '[additional_meetings]');
}
- function get_area_name($meeting_value)
+ function get_area_name(array $meeting_value): string
{
foreach (Bread_Bmlt::get_areas() as $unique_area) {
$area_data = explode(',', $unique_area);
@@ -522,11 +646,11 @@ function get_field($obj, $field)
{
$value = '';
if (isset($obj[$field])) {
- $value = Bread_Bmlt::parse_field($obj[$field]);
+ $value = Bread_Bmlt::parse_field($obj[$field]);
}
- return $value;
+ return $value;
}
- function write_service_meetings($font_size, $line_height)
+ function write_service_meetings()
{
if (isset($this->options['asm_template_content']) && trim($this->options['asm_template_content'])) {
$template = $this->options['asm_template_content'];
@@ -538,12 +662,12 @@ function write_service_meetings($font_size, $line_height)
if (empty($this->options['asm_format_key']) || $this->options['asm_format_key'] == 'ASM') {
$asm_query = true;
$sort_order = $this->options['asm_sort_order'];
- if ($sort_order=='same') {
+ if ($sort_order == 'same') {
$sort_order = 'weekday_tinyint,start_time';
}
$asm_id = "";
- if ($this->options['asm_format_key']==='ASM') {
- $asm_id = '&formats[]='.$this->formatsManager->getFormatByKey($this->options['weekday_language'], 'ASM');
+ if ($this->options['asm_format_key'] === 'ASM') {
+ $asm_id = '&formats[]=' . $this->formatsManager->getFormatByKey($this->options['weekday_language'], 'ASM');
}
$services = Bread_Bmlt::generateDefaultQuery();
if (!empty($this->options['asm_custom_query'])) {
@@ -551,23 +675,20 @@ function write_service_meetings($font_size, $line_height)
}
$asm_query = "client_interface/json/?switcher=GetSearchResults$services$asm_id&sort_keys=$sort_order";
// ASM can contain E-Mail and phone numbers that require logins.
- if ($this->options['asm_format_key']==='ASM') {
+ if ($this->options['asm_format_key'] === 'ASM') {
$asm_query .= "&advanced_published=0";
}
$results = Bread_Bmlt::get_configured_root_server_request($asm_query);
$service_meeting_result = json_decode(wp_remote_retrieve_body($results), true);
$this->adjust_timezone($service_meeting_result, $this->target_timezone);
- if ($sort_order == 'weekday_tinyint,start_time') {
- $service_meeting_result = $this->orderByWeekdayStart($service_meeting_result);
- }
}
if ($asm_query || $this->options['weekday_language'] != $this->options['asm_language']) {
foreach ($service_meeting_result as &$value) {
$value = $this->enhance_meeting($value, $this->options['asm_language']);
}
}
- $headerConfig = new Bread_Heading_Manager($this->options, $service_meeting_result, $this->options['asm_language'], 1);
- $this->writeMeetings($template, $headerConfig);
+ $meetingslistStructure = new Bread_Meetingslist_Structure($this->options, $service_meeting_result, $this->options['asm_language'], 1);
+ $this->writeMeetings($template, $meetingslistStructure);
return;
}
@@ -604,13 +725,13 @@ function adjust_timezone(&$meetings, $target_timezone)
date_timezone_set($date, $target_timezone);
$meeting['start_time'] = $date->format('H:i');
if ($date >= $target_midnight) {
- $meeting['weekday_tinyint'] = $meeting['weekday_tinyint']+1;
- if ($meeting['weekday_tinyint']==8) {
+ $meeting['weekday_tinyint'] = $meeting['weekday_tinyint'] + 1;
+ if ($meeting['weekday_tinyint'] == 8) {
$meeting['weekday_tinyint'] = 1;
}
} elseif ($date < $target_yesterday) {
- $meeting['weekday_tinyint'] = $meeting['weekday_tinyint']-1;
- if ($meeting['weekday_tinyint']==0) {
+ $meeting['weekday_tinyint'] = $meeting['weekday_tinyint'] - 1;
+ if ($meeting['weekday_tinyint'] == 0) {
$meeting['weekday_tinyint'] = 7;
}
}
diff --git a/public/class-bread-heading-manager.php b/public/class-bread-meetingslist-structure.php
similarity index 55%
rename from public/class-bread-heading-manager.php
rename to public/class-bread-meetingslist-structure.php
index c5a5b7f..3150b1f 100644
--- a/public/class-bread-heading-manager.php
+++ b/public/class-bread-meetingslist-structure.php
@@ -1,19 +1,85 @@
options['combine_headings'] = '';
if ($meeting_sort === 'user_defined') {
@@ -60,6 +126,17 @@ function upgradeHeaderData($meeting_sort)
$this->options['main_grouping'] = 'day';
}
}
+ /**
+ * Setup for structuring the meeting list
+ *
+ * @param array $options The configuration of the meeting list.
+ * @param array $result_meetings The meetings in the meeting list.
+ * @param string $lang The language of the meeting list
+ * @param integer $include_asm Whether or not to include meetings that match the requirements of the additional list. Where
+ * 0 - let everything through
+ * 1 - only meetings with asm format
+ * -1 - only meetings without asm format
+ */
function __construct(array $options, array $result_meetings, string $lang, int $include_asm)
{
$this->options = $options;
@@ -79,10 +156,10 @@ function __construct(array $options, array $result_meetings, string $lang, int $
}
$this->upgradeHeaderData($meeting_sort);
- $header_style = "color:".$options['header_text_color'].";";
- $header_style .= "background-color:".$options['header_background_color'].";";
- $header_style .= "font-size:".$options['header_font_size']."pt;";
- $header_style .= "line-height:".$options['content_line_height'].";";
+ $header_style = "color:" . $options['header_text_color'] . ";";
+ $header_style .= "background-color:" . $options['header_background_color'] . ";";
+ $header_style .= "font-size:" . $options['header_font_size'] . "pt;";
+ $header_style .= "line-height:" . $options['content_line_height'] . ";";
$header_style .= "text-align:center;padding-top:2px;padding-bottom:3px;";
if ($options['header_uppercase'] == 1) {
@@ -95,12 +172,17 @@ function __construct(array $options, array $result_meetings, string $lang, int $
$header_style .= 'font-weight: bold;';
}
$this->header_style = $header_style;
- $this->cont = '('.Bread::getTranslateTable()[$lang]['CONT'].')';
+ $this->cont = '(' . Bread::getTranslateTable()[$lang]['CONT'] . ')';
$this->headerMeetings = $this->getHeaderMeetings($result_meetings, $include_asm);
$this->unique_heading = $this->getUniqueHeadings($this->headerMeetings);
}
- function iterateMainHeading()
+ /**
+ * Iterates over the main headings in the meeting list
+ *
+ * @return array the list of sub-headings under this heading. If there are no sub-headings, an array with a single element is returned.
+ */
+ public function iterateMainHeading(): array
{
if ($this->main_index >= count($this->unique_heading)) {
return null;
@@ -114,12 +196,19 @@ function iterateMainHeading()
$this->sub_index = 0;
return $unique_subheading;
}
- function iterateSubHeading($unique_subheading, $still_new = false)
+ /**
+ * Iterates over the sub-headings in the current main heading.
+ *
+ * @param array $unique_subheading The list over which we are iterating.
+ * @param boolean $still_new a flag to indicate we are looking for the first subheading (we may skip some sub headings)
+ * @return array an array of the meetings in this subheading.
+ */
+ public function iterateSubHeading(array $unique_subheading, bool $still_new = false): array
{
if ($this->sub_index >= count($unique_subheading)) {
return null;
}
- $this->newMainHeading = ($this->sub_index==0) || $still_new;
+ $this->newMainHeading = ($this->sub_index == 0) || $still_new;
$this->sub_heading_raw = $unique_subheading[$this->sub_index++];
if ($this->skip_heading($this->sub_heading_raw)) {
return $this->iterateSubHeading($unique_subheading, $this->newMainHeading);
@@ -127,7 +216,13 @@ function iterateSubHeading($unique_subheading, $still_new = false)
$this->meeting_index = 0;
return $this->headerMeetings[$this->main_heading_raw][$this->sub_heading_raw];
}
- function iterateMeetings($meetings)
+ /**
+ * Iterates over the meetings in the current sub-heading.
+ *
+ * @param array $meetings
+ * @return array The next meeting
+ */
+ public function iterateMeetings(array $meetings): array
{
if ($this->meeting_index >= count($meetings)) {
return null;
@@ -135,20 +230,27 @@ function iterateMeetings($meetings)
$this->newMainHeading = $this->newMainHeading && $this->meeting_index == 0;
return $meetings[$this->meeting_index++];
}
- // include_asm = 0 - let everything through
- // 1 - only meetings with asm format
- // -1 - only meetings without asm format
- function getHeaderMeetings(&$result_meetings, $include_asm)
+ /**
+ * Does the work of structuring the meeting list into heading, subheadings and meetings.
+ *
+ * @param array $result_meetings The meetings returned from the BMLT root server query.
+ * @param integer $include_asm Whether or not to include meetings that match the requirements of the additional list. Where
+ * 0 - let everything through
+ * 1 - only meetings with asm format
+ * -1 - only meetings without asm format
+ * @return array The meetings, structured into an array with 3 levels. First level: main heading. Second level: sub headings, Third level: meetings.
+ */
+ private function getHeaderMeetings(array &$result_meetings, int $include_asm): array
{
$levels = $this->getHeaderLevels();
$headerMeetings = array();
foreach ($result_meetings as &$value) {
- $asm_test = $this->asm_test($value, $include_asm==1);
- if ((( $include_asm < 0 && $asm_test ) ||
- ( $include_asm > 0 && !$asm_test ))) {
- continue;
+ $asm_test = $this->asm_test($value, $include_asm == 1);
+ if ((($include_asm < 0 && $asm_test) ||
+ ($include_asm > 0 && !$asm_test))) {
+ continue;
}
- $main_grouping = $this->getHeaderItem($value, $this->setupDefaultHeading('main_'), $include_asm==1);
+ $main_grouping = $this->getHeaderItem($value, $this->setupDefaultHeading('main_'), $include_asm == 1);
if (!isset($headerMeetings[$main_grouping])) {
$headerMeetings[$main_grouping] = array();
if ($levels == 1) {
@@ -156,7 +258,7 @@ function getHeaderMeetings(&$result_meetings, $include_asm)
}
}
if ($levels == 2) {
- $subgrouping = $this->getHeaderItem($value, $this->setupDefaultHeading('sub'), $include_asm==1);
+ $subgrouping = $this->getHeaderItem($value, $this->setupDefaultHeading('sub'), $include_asm == 1);
if (!isset($headerMeetings[$main_grouping][$subgrouping])) {
$headerMeetings[$main_grouping][$subgrouping] = array();
}
@@ -167,50 +269,63 @@ function getHeaderMeetings(&$result_meetings, $include_asm)
}
return $headerMeetings;
}
- function getUniqueHeadings($headerMeetings)
+ /**
+ * Sort the headings alphabetically.
+ *
+ * @param [type] $headerMeetings
+ * @return array The sorted list.
+ */
+ public function getUniqueHeadings($headerMeetings): array
{
$unique_heading = array_keys($headerMeetings);
asort($unique_heading, SORT_NATURAL | SORT_FLAG_CASE);
return $unique_heading;
}
- function remove_sort_key($this_heading)
+ /**
+ * Main headings may contain [numbers] in the beginning, in case you don't want to sort alphebetically. These number can be added to a "filter"
+ * extension to enhance_meeting. This was added for New Zealand, who wants their cities sorted north-south. This gets the heading that we want to print.
+ *
+ * @param string $this_heading The raw heading
+ * @return string The heading with the [number] removed.
+ */
+ private function remove_sort_key(string $this_heading): string
{
- if (mb_substr($this_heading, 0, 1)=='[') {
+ if (mb_substr($this_heading, 0, 1) == '[') {
$end = strpos($this_heading, ']');
- if ($end>0) {
- return trim(substr($this_heading, $end+1));
+ if ($end > 0) {
+ return trim(substr($this_heading, $end + 1));
}
}
return $this_heading;
}
- function skip_heading($this_heading)
+ private function skip_heading(string $this_heading): bool
{
- return (mb_substr($this_heading, 0, 5)=='[XXX]');
+ return (mb_substr($this_heading, 0, 5) == '[XXX]');
}
- function getHeaderLevels()
+ private function getHeaderLevels(): int
{
if (!empty($options['subgrouping'])) {
return 2;
}
return 1;
}
- function setupDefaultHeading($level)
+ private function setupDefaultHeading(string $level): array
{
- return array(
- 'name' => $level.'grouping',
- 'name_alt' => $level.'grouping_alt',
- 'name_suffix' => $level.'grouping_alt',
- 'name_alt_suffix' => $level.'grouping_alt',
- );
+ return array(
+ 'name' => $level . 'grouping',
+ 'name_alt' => $level . 'grouping_alt',
+ 'name_suffix' => $level . 'grouping_alt',
+ 'name_alt_suffix' => $level . 'grouping_alt',
+ );
}
- function getHeaderItem($value, $names)
+ private function getHeaderItem(array $value, array $names): string
{
if (!$this->options[$names['name']]) {
- return '';
+ return '';
}
$grouping = '';
$name = $this->options[$names['name']];
- if ($name=='service_body_bigint') {
+ if ($name == 'service_body_bigint') {
foreach (Bread_Bmlt::get_areas() as $unique_area) {
$area_data = explode(',', $unique_area);
$area_name = Bread::arraySafeGet($area_data);
@@ -220,32 +335,33 @@ function getHeaderItem($value, $names)
}
}
return 'Area not found';
- } elseif ($name=='day') {
+ } elseif ($name == 'day') {
$off = intval($this->options['weekday_start']);
$day = intval($value['weekday_tinyint']);
if ($day < $off) {
$day = $day + 7;
}
- return '['.str_pad($day, 2, '0', STR_PAD_LEFT).']'.$value['day'];
+ return '[' . str_pad($day, 2, '0', STR_PAD_LEFT) . ']' . $value['day'];
} elseif (isset($value[$name])) {
$grouping = Bread_Bmlt::parse_field($value[$name]);
}
$suffix = $this->options[$names['name_suffix']] ?? '';
- if ($grouping==''
+ if ($grouping == ''
&& !empty($name_alt)
- && isset($value[$name_alt])) {
+ && isset($value[$name_alt])
+ ) {
$grouping = Bread_Bmlt::parse_field($value[$name_alt]);
$suffix = $this->options[$names['name_alt_suffix']] ?? '';
}
- if (strlen(trim($grouping))==0) {
+ if (strlen(trim($grouping)) == 0) {
return 'NO DATA';
}
if (!empty($suffix)) {
- return $grouping.' '.$suffix;
+ return $grouping . ' ' . $suffix;
}
return $grouping;
}
- function asm_test($value, $flag = false)
+ private function asm_test(array $value, $flag = false): bool
{
if (empty($this->options['asm_format_key'])) {
return false;
@@ -263,7 +379,7 @@ function asm_test($value, $flag = false)
$enFormats = explode(",", $value['formats']);
return in_array($format_key, $enFormats);
}
- function isHybrid($value)
+ private function isHybrid(array $value): bool
{
if (empty($value['formats'])) {
return false;
@@ -271,7 +387,7 @@ function isHybrid($value)
$enFormats = explode(",", $value['formats']);
return in_array('HY', $enFormats);
}
- function isVirtual($value)
+ private function isVirtual(array $value): bool
{
if (empty($value['formats'])) {
return false;
@@ -279,43 +395,43 @@ function isVirtual($value)
$enFormats = explode(",", $value['formats']);
return in_array('VM', $enFormats);
}
- function calculateHeading()
+ public function calculateHeading(): string
{
$header = '';
- if ($this->options['suppress_heading']==1) {
+ if ($this->options['suppress_heading'] == 1) {
return $header;
}
$this_heading = $this->remove_sort_key($this->main_heading_raw);
$this_subheading = $this->remove_sort_key($this->sub_heading_raw);
- if (($this->meeting_index==1) && !empty($options['combine_headings'])) {
+ if (($this->meeting_index == 1) && !empty($options['combine_headings'])) {
$header_string = $this->options['combine_headings'];
$header_string = str_replace('main_grouping', $this_heading, $header_string);
$header_string = str_replace('subgrouping', $this_subheading, $header_string);
- $header .= "".$header_string."
";
+ $header .= "" . $header_string . "
";
} elseif (!empty($options['subgrouping'])) {
- if ($this->main_index==1) {
+ if ($this->main_index == 1) {
$xtraMargin = '';
- if (!$this->main_index>1 or $this->meeting_index>1) {
+ if (!$this->main_index > 1 or $this->meeting_index > 1) {
$xtraMargin = 'margin-top:2pt;';
}
- $header .= ''.$this_heading."
";
+ $header .= '' . $this_heading . "
";
}
- if (($this->meeting_index==1) && $this->options['sub_header_shown']=='display') {
- $header .= "".$this_subheading."
";
+ if (($this->meeting_index == 1) && $this->options['sub_header_shown'] == 'display') {
+ $header .= "" . $this_subheading . "
";
}
} elseif ($this->newMainHeading) {
- $header .= "".$this_heading."
";
+ $header .= "" . $this_heading . "
";
}
return $header;
}
- function calculateContHeader()
+ public function calculateContHeader(): string
{
$header = '';
- if ($this->options['suppress_heading']==1) {
+ if ($this->options['suppress_heading'] == 1) {
return $header;
}
if (!$this->newMainHeading && $this->options['cont_header_shown']) {
- $header = "".$this->remove_sort_key($this->main_heading_raw)." " . $this->cont . "
";
+ $header = "" . $this->remove_sort_key($this->main_heading_raw) . " " . $this->cont . "
";
}
return $header;
}