mirror of
				https://github.com/dwaxweiler/connector-mobilizon
				synced 2025-06-05 21:59:25 +02:00 
			
		
		
		
	wip
This commit is contained in:
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -3,3 +3,5 @@ build/ | ||||
| coverage/ | ||||
| node_modules/ | ||||
| vendor/ | ||||
|  | ||||
| .phpunit.result.cache | ||||
|   | ||||
| @@ -38,7 +38,7 @@ The current changelog can be under [source/changelog.txt](source/changelog.txt). | ||||
|  | ||||
| - Run ESLint: `npm run eslint` | ||||
| - Run JavaScript code coverage with tests: `npm run coverage` | ||||
| - Run tests: `npm test` | ||||
| - Run tests: `npm test` & `./vendor/bin/phpunit tests` (`composer dump-autoload -o` after newly created class) | ||||
| - Delete build folder: `npm run clean` | ||||
| - Update PHP dependencies: `composer update` | ||||
| - Check for direct PHP dependency updates: `composer outdated --direct` | ||||
|   | ||||
| @@ -1 +1,10 @@ | ||||
| {} | ||||
| { | ||||
|   "autoload": { | ||||
|     "classmap": [ | ||||
|       "source/includes" | ||||
|     ] | ||||
|   }, | ||||
|   "require-dev": { | ||||
|     "phpunit/phpunit": "^9.5" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										2103
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2103
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -12,6 +12,9 @@ | ||||
|  | ||||
| require_once __DIR__ . '/includes/constants.php'; | ||||
| require_once __DIR__ . '/includes/settings.php'; | ||||
| require_once __DIR__ . '/includes/date-time-wrapper.php'; | ||||
| require_once __DIR__ . '/includes/formatter.php'; | ||||
| require_once __DIR__ . '/includes/graphql-client.php'; | ||||
| require_once __DIR__ . '/includes/events-list-shortcut.php'; | ||||
| require_once __DIR__ . '/includes/events-list-widget.php'; | ||||
|  | ||||
|   | ||||
							
								
								
									
										33
									
								
								source/includes/date-time-wrapper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								source/includes/date-time-wrapper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| <?php | ||||
|  | ||||
| final class DateTimeWrapper { | ||||
|   private $dateTime; | ||||
|   private $locale; | ||||
|   private $timeZone; | ||||
|  | ||||
|   public function __construct(string $text, string $locale = 'en-GB', string $timeZone = 'utc') { | ||||
|     if (!$locale) { | ||||
|       $locale = 'en-GB'; | ||||
|     } | ||||
|     if (!$timeZone) { | ||||
|       $timeZone = 'utc'; | ||||
|     } | ||||
|     $this->dateTime = new DateTime($text); | ||||
|     $this->locale = $locale; | ||||
|     $this->timeZone = new DateTimeZone($timeZone); | ||||
|   } | ||||
|  | ||||
|   public function getShortDate(): string { | ||||
|     $formatter = IntlDateFormatter::create($this->locale, IntlDateFormatter::SHORT, IntlDateFormatter::NONE, $this->timeZone); | ||||
|     return $formatter->format($this->dateTime); | ||||
|   } | ||||
|  | ||||
|   public function getOffset(): string { | ||||
|     return $this->timeZone->getOffset($this->dateTime); | ||||
|   } | ||||
|  | ||||
|   public function get24Time(): string { | ||||
|     $formatter = IntlDateFormatter::create($this->locale, IntlDateFormatter::NONE, IntlDateFormatter::SHORT, $this->timeZone); | ||||
|     return $formatter->format($this->dateTime); | ||||
|   } | ||||
| } | ||||
| @@ -27,12 +27,18 @@ class EventsListWidget extends \WP_Widget { | ||||
|  | ||||
|     $classNamePrefix = NAME; | ||||
|     $eventsCount = $options['eventsCount']; | ||||
|     $locale = str_replace('_', '-', get_locale()); | ||||
|     $locale = str_replace('_', '-', get_locale()); // TODO _ is okay too. | ||||
|     $groupName = isset($options['groupName']) ? $options['groupName'] : ''; | ||||
|     $url = Settings::getUrl(); | ||||
|     $timeZone = wp_timezone_string(); | ||||
|     $isShortOffsetNameShown = Settings::isShortOffsetNameShown(); | ||||
|  | ||||
|     if ($groupName) { | ||||
|       $data = GraphQlClient::get_upcoming_events_by_group_name($url, (int) $eventsCount, $groupName); // TODO wrap and put into shortcut as well | ||||
|     } else { | ||||
|       $data = GraphQlClient::get_upcoming_events($url, (int) $eventsCount); | ||||
|     } | ||||
|  | ||||
|     require dirname(__DIR__) . '/view/events-list.php'; | ||||
|  | ||||
|     echo $args['after_widget']; | ||||
|   | ||||
							
								
								
									
										40
									
								
								source/includes/formatter.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								source/includes/formatter.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| <?php | ||||
| final class Formatter | ||||
| { | ||||
|   public static function format_date(string $locale, string $timeZone, string $start, ?string $end, bool $isShortOffsetNameShown): string { | ||||
|     $startDateTime = new DateTimeWrapper($start, $locale, $timeZone); | ||||
|     $dateText = $startDateTime->getShortDate(); | ||||
|     $dateText .= ' ' . $startDateTime->get24Time(); | ||||
|     if (!$end && $isShortOffsetNameShown) { | ||||
|       $dateText .= ' (' . $startDateTime->getOffset() . ')'; | ||||
|     } | ||||
|     if ($end) { | ||||
|       $endDateTime = new DateTimeWrapper($end, $locale, $timeZone); | ||||
|       if ($startDateTime->getShortDate() != $endDateTime->getShortDate()) { | ||||
|         $dateText .= ' - '; | ||||
|         $dateText .= $endDateTime->getShortDate() . ' '; | ||||
|       } else { | ||||
|         $dateText .= ' - '; | ||||
|       } | ||||
|       $dateText .= $endDateTime->get24Time(); | ||||
|       if ($isShortOffsetNameShown) { | ||||
|         $dateText .= ' (' . $endDateTime->getOffset() . ')'; | ||||
|       } | ||||
|     } | ||||
|     return $dateText; | ||||
|   } | ||||
|  | ||||
|   public static function format_location(string $description, string $locality): string { | ||||
|     $location = ''; | ||||
|     if ($description && trim($description)) { | ||||
|       $location .= trim($description); | ||||
|     } | ||||
|     if ($location && $locality) { | ||||
|       $location .= ', '; | ||||
|     } | ||||
|     if ($locality) { | ||||
|       $location .= $locality; | ||||
|     } | ||||
|     return $location; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										116
									
								
								source/includes/graphql-client.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								source/includes/graphql-client.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,116 @@ | ||||
| <?php | ||||
| namespace MobilizonConnector; | ||||
|  | ||||
| // Exit if this file is called directly. | ||||
| if (!defined('ABSPATH')) { | ||||
|   exit; | ||||
| } | ||||
|  | ||||
| final class GraphQlClient { | ||||
|  | ||||
|   public static function query(string $endpoint, string $query, array $variables = [], ?string $token = null): array | ||||
|   { | ||||
|     $headers = ['Content-Type: application/json']; | ||||
|     if ($token !== null) { | ||||
|         $headers[] = "Authorization: bearer $token"; | ||||
|     } | ||||
|  | ||||
|     $context = stream_context_create([ | ||||
|         'http' => [ | ||||
|             'method' => 'POST', | ||||
|             'header' => $headers, | ||||
|             'content' => json_encode(['query' => $query, 'variables' => $variables]), | ||||
|         ] | ||||
|       ]); | ||||
|     $data = @file_get_contents($endpoint, false, $context); | ||||
|  | ||||
|     if ($data === false) { | ||||
|       $error = error_get_last(); | ||||
|       throw new \ErrorException($error['message'], $error['type']); | ||||
|     } | ||||
|  | ||||
|     return json_decode($data, true); | ||||
|   } | ||||
|  | ||||
|   public static function get_upcoming_events(string $url, int $limit): array { | ||||
|     $query = <<<'GRAPHQL' | ||||
|       query ($limit: Int) { | ||||
|         events(limit: $limit) { | ||||
|           elements { | ||||
|             id, | ||||
|             title, | ||||
|             url, | ||||
|             beginsOn, | ||||
|             endsOn, | ||||
|             physicalAddress { | ||||
|               description, | ||||
|               locality | ||||
|             } | ||||
|           }, | ||||
|           total | ||||
|         } | ||||
|       } | ||||
|       GRAPHQL; | ||||
|  | ||||
|     $endpoint = $url . '/api'; | ||||
|     // const dataInCache = SessionCache.get(sessionStorage, { | ||||
|     //   url, | ||||
|     //   query, | ||||
|     //   variables: { limit }, | ||||
|     // }) | ||||
|     // if (dataInCache !== null) { | ||||
|     //   return Promise.resolve(dataInCache) | ||||
|     // } | ||||
|     $data = self::query($endpoint, $query, ['limit' => $limit]); | ||||
|       // SessionCache.add(sessionStorage, { url, query, variables: { limit } }, data) | ||||
|     return $data; | ||||
|   } | ||||
|  | ||||
|   public static function get_upcoming_events_by_group_name(string $url, int $limit, string $groupName): array { | ||||
|     $query = <<<'GRAPHQL' | ||||
|       query ($afterDatetime: DateTime, $groupName: String, $limit: Int) { | ||||
|         group(preferredUsername: $groupName) { | ||||
|           organizedEvents(afterDatetime: $afterDatetime, limit: $limit) { | ||||
|             elements { | ||||
|               id, | ||||
|               title, | ||||
|               url, | ||||
|               beginsOn, | ||||
|               endsOn, | ||||
|               physicalAddress { | ||||
|                 description, | ||||
|                 locality | ||||
|               } | ||||
|             }, | ||||
|             total | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|       GRAPHQL; | ||||
|  | ||||
|     $endpoint = $url . '/api'; | ||||
|  | ||||
|     // const afterDatetime = DateTimeWrapper.getCurrentDatetimeAsString() | ||||
|     // const dataInCache = SessionCache.get(sessionStorage, { | ||||
|     //   url, | ||||
|     //   query, | ||||
|     //   variables: { afterDatetime, groupName, limit }, | ||||
|     // }) | ||||
|     // if (dataInCache !== null) { | ||||
|     //   return Promise.resolve(dataInCache) | ||||
|     // } | ||||
|     $afterDatetime = date(DateTime::ISO8601); | ||||
|     $data = self::query($endpoint, $query, ['afterDatetime'=> $afterDatetime, 'groupName' => $groupName, 'limit' => $limit]); | ||||
|     // return request(url, query, { afterDatetime, groupName, limit }).then( | ||||
|     //   (data) => { | ||||
|     //     SessionCache.add( | ||||
|     //       sessionStorage, | ||||
|     //       { url, query, variables: { afterDatetime, groupName, limit } }, | ||||
|     //       data | ||||
|     //     ) | ||||
|     //     return Promise.resolve(data) | ||||
|     //   } | ||||
|     // ) | ||||
|     return $data; | ||||
|   } | ||||
| } | ||||
| @@ -14,3 +14,18 @@ if (!defined('ABSPATH')) { | ||||
|   <li style="display: none;"><?php esc_html_e('The events could not be loaded!', 'connector-mobilizon'); ?></li> | ||||
|   <li style="display: none;"><?php esc_html_e('The group could not be found!', 'connector-mobilizon'); ?></li> | ||||
| </ul> | ||||
|  | ||||
| <?php /*print_r($data);*/ ?> | ||||
| <ul> | ||||
| <?php foreach($data['data']['events']['elements'] as $event) { ?> | ||||
|   <li> | ||||
|     <a href="<?php echo esc_attr($event['url']); ?>"><?php echo esc_html_e($event['title']); ?></a> | ||||
|     <br> | ||||
|     <?php echo esc_html_e(Formatter::format_date($locale, $timeZone, $event['beginsOn'], $event['endsOn'], $isShortOffsetNameShown)); ?> | ||||
|     <?php if (isset($event['physicalAddress'])) { ?> | ||||
|     <br> | ||||
|     <?php echo esc_html_e(Formatter::format_location($event['physicalAddress']['description'], $event['physicalAddress']['locality'])) ?> | ||||
|     <?php } ?> | ||||
|   </li> | ||||
| <?php } ?> | ||||
| </ul> | ||||
|   | ||||
							
								
								
									
										39
									
								
								tests/DateTimeWrapperTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								tests/DateTimeWrapperTest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
| use PHPUnit\Framework\TestCase; | ||||
|  | ||||
| final class DateTimeWrapperTest extends TestCase { | ||||
|   public function testCanGetShortDateForUsualDate(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z'); | ||||
|     $this->assertEquals('24/12/2020', $d->getShortDate()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGetShortDateForUsualDateWithTimezoneString(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z', 'en-GB', 'Europe/Rome'); | ||||
|     $this->assertEquals('24/12/2020', $d->getShortDate()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGetShortDateForUsualDateWithNamedOffset(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z', 'en-GB', 'UTC'); | ||||
|     $this->assertEquals('24/12/2020', $d->getShortDate()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGetShortDateForUsualDateWithOffset(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z', 'en-GB', '+02:00'); | ||||
|     $this->assertEquals('24/12/2020', $d->getShortDate()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGetShortDateForUsualDateWithEmptyTimezone(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z', 'en-GB', ''); | ||||
|     $this->assertEquals('24/12/2020', $d->getShortDate()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGet24TimeForUsualTime(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z'); | ||||
|     $this->assertEquals('16:45', $d->get24Time()); | ||||
|   } | ||||
|  | ||||
|   public function testCanGetShortOffsetNameForUsualTime(): void { | ||||
|     $d = new DateTimeWrapper('2020-12-24T16:45:00Z'); | ||||
|     $this->assertEquals(0, $d->getOffset()); // TODO was UTC | ||||
|   }   | ||||
| } | ||||
							
								
								
									
										45
									
								
								tests/FormatterTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								tests/FormatterTest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <?php | ||||
| use PHPUnit\Framework\TestCase; | ||||
|  | ||||
| final class FormatterTest extends TestCase | ||||
| { | ||||
|   public function testCanDateFormatOneDate(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30 - 15:30', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', '2021-04-15T15:30:00Z', false)); | ||||
|   } | ||||
|  | ||||
|   public function testCanDateFormatOneDateWithOffset(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30 - 15:30 (0)', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', '2021-04-15T15:30:00Z', true)); | ||||
|   } | ||||
|    | ||||
|   public function testCanDateFormatTwoDates(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30 - 16/04/2021 15:30', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', '2021-04-16T15:30:00Z', false)); | ||||
|   } | ||||
|    | ||||
|   public function testCanDateFormatTwoDatesWithOffset(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30 - 16/04/2021 15:30 (0)', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', '2021-04-16T15:30:00Z', true)); | ||||
|   } | ||||
|    | ||||
|   public function testCanDateFormatWhenSecondDateIsNull(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', null, false)); | ||||
|   } | ||||
|    | ||||
|   public function testCanDateFormatWhenSecondDateIsNullWithOffset(): void { | ||||
|     $this->assertEquals('15/04/2021 10:30 (0)', Formatter::format_date('en-GB', 'UTC', '2021-04-15T10:30:00Z', null, true)); | ||||
|   } | ||||
|  | ||||
|   public function testCanLocationFormatBothParameters(): void { | ||||
|     $this->assertEquals('a, b', Formatter::format_location('a', 'b')); | ||||
|   } | ||||
|  | ||||
|   public function testLocationFormatDescriptionOnly(): void { | ||||
|     $this->assertEquals('a', Formatter::format_location('a', '')); | ||||
|   } | ||||
|  | ||||
|   public function testLocationFormatDescriptionWithSpaceOnly() { | ||||
|     $this->assertEquals('', Formatter::format_location(' ', '')); | ||||
|   } | ||||
|  | ||||
|   public function testLocationFormatLocalityOnly(): void { | ||||
|     $this->assertEquals('a', Formatter::format_location('', 'a')); | ||||
|   } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user