Skip to content

Commit

Permalink
v1.7.0 (#68)
Browse files Browse the repository at this point in the history
  • Loading branch information
bfren authored Aug 28, 2023
2 parents 7af011d + fab69a7 commit f72a051
Show file tree
Hide file tree
Showing 73 changed files with 533 additions and 382 deletions.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.6.2
1.7.0
2 changes: 1 addition & 1 deletion VERSION_MINOR
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.6
1.7
28 changes: 20 additions & 8 deletions config-sample.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
general:
church_suite_org: ''
church_suite_api: ''
church_name: ''
church_name_full: ''
church_domain: ''
production: true

airtable:
Expand All @@ -10,6 +11,13 @@ airtable:
cache:
duration_in_seconds: 3600

church_suite:
api_application: ''
api_key: ''
org: ''
tag_id_adults: 1
tag_id_children: 2

events:
cancelled_flag: '[Cancelled]'
default_location: 'Church'
Expand Down Expand Up @@ -38,6 +46,16 @@ login:
max_attempts: 5
pass: ''

prayer:
day_29: [ '' ]
day_30: [ '' ]
day_31: [ '' ]
footer_page_1_left: 'If you don’t know someone, or don’t know what to say, you could pray...'
footer_page_1_right: '<strong>&lsquo;Father, may <em>N</em> know your love, be filled with your Spirit, and share Jesus in all they do and say.&rsquo;</strong>'
footer_page_2_left: 'Privacy Policy'
footer_page_2_right: 'If you don&rsquo;t wish to be included, you can remove yourself in Church Suite or by contacting the office.'
show_last_name: true

refresh:
days_before: 7
days_after: 2
Expand All @@ -52,9 +70,3 @@ rota:
- { name: 'President', abbv: 'Ps' }
- { name: 'Readings', desc: 'Reader', abbv: 'R' }
- { name: 'Service Leader', desc: 'Leader', abbv: 'L' }

prayer:
day_29: [ '' ]
day_30: [ '' ]
day_31: [ '' ]
show_last_name: true
2 changes: 1 addition & 1 deletion docker/overlay/tmp/PHP_BUILD
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8.2.8-r0
8.2.9-r0
3 changes: 2 additions & 1 deletion src/app.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class App
private const CHECK = "CHECK";

/**
* Application version.
* Application version - this is set using the version in the source / container image VERSION file (see init).
*
* @var string
*/
Expand Down Expand Up @@ -71,6 +71,7 @@ public static function init(): void

// require function scripts
require_once "functions/escape.php";
require_once "functions/log.php";
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/classes/airtable/airtable.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class Airtable
private readonly string $url;

/**
* Connect to the Airtable API for the specified table.
* Build URL to connect to the specified table.
*
* @param string $table Table name.
* @return void
Expand Down
33 changes: 25 additions & 8 deletions src/classes/cache/cache.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@
use Feeds\App;
use Feeds\Bible\Bible_Plan;
use Feeds\Calendar\Event;
use Feeds\ChurchSuite\Api;
use Feeds\Helpers\Hash;
use Feeds\Lectionary\Lectionary;
use Feeds\Prayer\Person;
use Feeds\Prayer\Prayer_Calendar;
use Feeds\Refresh\Refresh;
use Feeds\Request\Request;
Expand All @@ -32,6 +34,11 @@ class Cache
*/
public const LECTIONARY = "lectionary";

/**
* People cache name.
*/
public const PEOPLE = "people";

/**
* Prayer Calendar cache name.
*/
Expand Down Expand Up @@ -113,6 +120,16 @@ public static function clear_lectionary(): void
self::clear(self::LECTIONARY);
}

/**
* Clear the People cache.
*
* @return void
*/
public static function clear_people(): void
{
self::clear(self::PEOPLE);
}

/**
* Clear the Prayer Calendar cache.
*
Expand Down Expand Up @@ -225,24 +242,24 @@ public static function get_lectionary_last_modified(): int
}

/**
* Get Prayer calendar from the cache (or generate a fresh copy).
* Get People from the cache (or retrieve from ChurchSuite).
*
* @param bool $force If true, $callable will be used whether or not the cache entry has expired.
* @return Prayer_Calendar Prayer Calendar object.
* @return Person[] Array of People.
*/
public static function get_prayer_calendar(bool $force = false): Prayer_Calendar
public static function get_people(bool $force = false): array
{
return self::get_or_set(self::PRAYER, fn () => new Prayer_Calendar(), force: $force);
return self::get_or_set(self::PEOPLE, fn () => Api::get_prayer_calendar_people(), force: $force);
}

/**
* Get the Prayer calendar last modified timestamp.
* Get the People last modified timestamp.
*
* @return int Prayer calendar last modified timestamp.
* @return int People last modified timestamp.
*/
public static function get_prayer_calendar_last_modified(): int
public static function get_people_last_modified(): int
{
$path = self::get_cache_file_path(self::PRAYER);
$path = self::get_cache_file_path(self::PEOPLE);
return self::get_last_modified($path);
}

Expand Down
6 changes: 3 additions & 3 deletions src/classes/calendar/vcal.class.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ public function print_output(): void
// begin calendar definition
$this->lines[] = "BEGIN:VCALENDAR";
$this->lines[] = "VERSION:2.0";
$this->lines[] = "PRODID:-//bfren.dev//NONSGML//EN";
$this->lines[] = sprintf("PRODID:-//%s//NONSGML//EN", C::$general->church_domain);
$this->lines[] = "CALSCALE:GREGORIAN";
$this->lines[] = "X-PUBLISHED-TTL:PT1H";

// add timezone definition
$tz = self::get_ical_timezone(C::$events->timezone)?->get_definition();
if($tz) {
if ($tz) {
$this->lines = array_merge($this->lines, $tz);
}

Expand Down Expand Up @@ -111,7 +111,7 @@ public function print_output(): void
* @param Event $event The event to add.
* @return void
*/
private function add_event(Event $event):void
private function add_event(Event $event): void
{
$tzid = $event->start->getTimezone()->getName();

Expand Down
127 changes: 127 additions & 0 deletions src/classes/churchsuite/api.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace Feeds\ChurchSuite;

use Feeds\App;
use Feeds\Config\Config as C;
use Feeds\Helpers\Arr;
use Feeds\Helpers\Hash;
use Feeds\Prayer\Person;
use Feeds\Prayer\Prayer_Calendar;

App::check();

class Api
{
/**
* ChurchSuite API version.
*
* @var string
*/
private readonly string $version;

/**
* Set the version to use for all API requests.
*
* @return void
*/
public function __construct()
{
$this->version = "v1";
}

/**
* Make a request to the ChurchSuite API and return the response - logging any errors.
*
* @param string $endpoint ChurchSuite API endpoint.
* @param array $data Request data.
* @return mixed API response.
*/
private function make_request(string $endpoint, array $data): mixed
{
// build URL from data
$url = sprintf("https://api.churchsuite.com/%s/%s?%s", $this->version, $endpoint, http_build_query($data));

// create curl request
$handle = curl_init($url);
curl_setopt($handle, CURLOPT_HTTPHEADER, array(
sprintf("X-Account: %s", C::$churchsuite->org),
sprintf("X-Application: %s", C::$churchsuite->api_application),
sprintf("X-Auth: %s", C::$churchsuite->api_key)
));
curl_setopt($handle, CURLOPT_RETURNTRANSFER, 1);

// make request - on error log and return null
$json = curl_exec($handle);
if (!$json) {
_l(print_r(curl_error($handle), true));
return null;
}

// decode JSON response - on error log and return null
$result = json_decode($json, true);
if (!$result) {
_l("Unable to decode JSON response from %s", $url);
return null;
} elseif (isset($result["error"])) {
_l("Error retrieving %s: %s", $url, $result["error"]["message"]);
return null;
}

return $result;
}

/**
* Make a request to the ChurchSuite API to get people.
*
* @param string $endpoint API endpoint (e.g. 'addressbook/contacts').
* @param string $kind The kind of people being requested ('contacts' or 'children').
* @param bool $are_children Whether or not the people being requested are children.
* @return Person[] Array of Person objects where the key is a unique hash (see Hash::person).
*/
private function get_people(string $endpoint, string $kind, bool $are_children): array
{
// make request and return empty array on failure
$response = $this->make_request($endpoint, array($kind => "true"));
if ($response === null) {
return array();
}

// build array of People from the response
$people = array();
foreach ($response[$kind] as $person) {
$thumb_url = Arr::get(Arr::get(Arr::get($person, "images", array()), "md", array()), "url");
$person = new Person(
first_name: $person["first_name"],
last_name: $person["last_name"],
is_child: $are_children,
image_url: $thumb_url
);
$people[Hash::person($person)] = $person;
}

// return - the list is returned sorted by ChurchSuite
return $people;
}

/**
* Get everyone who has consented to being in the Prayer Calendar.
*
* @return Person[] Array of Person objects where the key is a unique hash (see Hash::person).
*/
public static function get_prayer_calendar_people(): array
{
// create API object
$api = new Api();

// get adults and children with the Prayer Calendar tag
$contacts = $api->get_people(sprintf("addressbook/tag/%s", C::$churchsuite->tag_id_adults), "contacts", false);
$children = $api->get_people(sprintf("children/tag/%s", C::$churchsuite->tag_id_children), "children", true);

// merge and sort array
$people = array_merge($contacts, $children);
Prayer_Calendar::sort_people($people);

return $people;
}
}
61 changes: 61 additions & 0 deletions src/classes/config/config-churchsuite.class.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<?php

namespace Feeds\Config;

use Feeds\App;
use Feeds\Helpers\Arr;

App::check();

class Config_ChurchSuite
{
/**
* Church Suite API application.
*
* @var string
*/
public readonly string $api_application;

/**
* Church Suite API key.
*
* @var string
*/
public readonly string $api_key;

/**
* Church Suite organisation subdomain (e.g. 'kingshope' for 'kingshope.churchsuite.com').
*
* @var string
*/
public readonly string $org;

/**
* Church Suite Tag ID for adults who have consented to be in the Prayer Calendar.
*
* @var int
*/
public readonly int $tag_id_adults;

/**
* Church Suite Tag ID for children whose parents have consented for them to be in the Prayer Calendar.
*
* @var int
*/
public readonly int $tag_id_children;

/**
* Get values from general configuration array.
*
* @param array $config General configuration array.
* @return void
*/
public function __construct(array $config)
{
$this->api_application = Arr::get($config, "api_application", "");
$this->api_key = Arr::get($config, "api_key", "");
$this->org = Arr::get($config, "org", "");
$this->tag_id_adults = Arr::get_integer($config, "tag_id_adults", 0);
$this->tag_id_children = Arr::get_integer($config, "tag_id_children", 0);
}
}
Loading

0 comments on commit f72a051

Please sign in to comment.