From 5cf6be34a269c9940c41b46fb902439a5aa6f61a Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Sun, 9 Dec 2018 01:00:22 -0700 Subject: [PATCH] Add member roster generator (#7) --- composer.json | 4 +- composer.lock | 431 ++++++++++++++++++++++++++- langs/en/messages.json | 3 +- lib/mkmemberdirectory.php | 227 ++++++++++++++ static/img/export/child.png | Bin 0 -> 331 bytes static/img/export/empty.png | Bin 0 -> 157 bytes static/img/export/graduation-cap.png | Bin 0 -> 550 bytes static/img/export/no-camera.png | Bin 0 -> 1135 bytes 8 files changed, 662 insertions(+), 3 deletions(-) create mode 100644 lib/mkmemberdirectory.php create mode 100644 static/img/export/child.png create mode 100644 static/img/export/empty.png create mode 100644 static/img/export/graduation-cap.png create mode 100644 static/img/export/no-camera.png diff --git a/composer.json b/composer.json index ea90c45..3955af9 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,9 @@ "require": { "catfan/medoo": "^1.5", "guzzlehttp/guzzle": "^6.2", - "stripe/stripe-php": "^6.24" + "stripe/stripe-php": "^6.24", + "dompdf/dompdf": "^0.8.2", + "phpoffice/phpword": "^0.15.0" }, "license": "MPL-2.0", "authors": [ diff --git a/composer.lock b/composer.lock index 5535e42..a54d4e5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "87c8c709e248bfe62291e8208765fd01", + "content-hash": "6f34e806ca8d5a98ea5816ce6865c253", "packages": [ { "name": "catfan/medoo", @@ -65,6 +65,68 @@ ], "time": "2018-06-14T18:59:08+00:00" }, + { + "name": "dompdf/dompdf", + "version": "v0.8.2", + "source": { + "type": "git", + "url": "https://github.com/dompdf/dompdf.git", + "reference": "5113accd9ae5d466077cce5208dcf3fb871bf8f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/5113accd9ae5d466077cce5208dcf3fb871bf8f6", + "reference": "5113accd9ae5d466077cce5208dcf3fb871bf8f6", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-gd": "*", + "ext-mbstring": "*", + "phenx/php-font-lib": "0.5.*", + "phenx/php-svg-lib": "0.3.*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "4.8.*", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.7-dev" + } + }, + "autoload": { + "psr-4": { + "Dompdf\\": "src/" + }, + "classmap": [ + "lib/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + }, + { + "name": "Brian Sweeney", + "email": "eclecticgeek@gmail.com" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com" + } + ], + "description": "DOMPDF is a CSS 2.1 compliant HTML to PDF converter", + "homepage": "https://github.com/dompdf/dompdf", + "time": "2017-11-26T14:49:08+00:00" + }, { "name": "guzzlehttp/guzzle", "version": "6.3.3", @@ -246,6 +308,284 @@ ], "time": "2017-03-20T17:10:46+00:00" }, + { + "name": "pclzip/pclzip", + "version": "2.8.2", + "source": { + "type": "git", + "url": "https://github.com/ivanlanin/pclzip.git", + "reference": "19dd1de9d3f5fc4d7d70175b4c344dee329f45fd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ivanlanin/pclzip/zipball/19dd1de9d3f5fc4d7d70175b4c344dee329f45fd", + "reference": "19dd1de9d3f5fc4d7d70175b4c344dee329f45fd", + "shasum": "" + }, + "type": "library", + "autoload": { + "classmap": [ + "pclzip.lib.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1" + ], + "authors": [ + { + "name": "Vincent Blavet" + } + ], + "description": "A PHP library that offers compression and extraction functions for Zip formatted archives", + "homepage": "http://www.phpconcept.net/pclzip", + "keywords": [ + "php", + "zip" + ], + "time": "2014-06-05T11:42:24+00:00" + }, + { + "name": "phenx/php-font-lib", + "version": "0.5.1", + "source": { + "type": "git", + "url": "https://github.com/PhenX/php-font-lib.git", + "reference": "760148820110a1ae0936e5cc35851e25a938bc97" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhenX/php-font-lib/zipball/760148820110a1ae0936e5cc35851e25a938bc97", + "reference": "760148820110a1ae0936e5cc35851e25a938bc97", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "FontLib\\": "src/FontLib" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse, export and make subsets of different types of font files.", + "homepage": "https://github.com/PhenX/php-font-lib", + "time": "2017-09-13T16:14:37+00:00" + }, + { + "name": "phenx/php-svg-lib", + "version": "v0.3.2", + "source": { + "type": "git", + "url": "https://github.com/PhenX/php-svg-lib.git", + "reference": "ccc46ef6340d4b8a4a68047e68d8501ea961442c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PhenX/php-svg-lib/zipball/ccc46ef6340d4b8a4a68047e68d8501ea961442c", + "reference": "ccc46ef6340d4b8a4a68047e68d8501ea961442c", + "shasum": "" + }, + "require": { + "sabberworm/php-css-parser": "8.1.*" + }, + "require-dev": { + "phpunit/phpunit": "~5.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "Svg\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Fabien Ménager", + "email": "fabien.menager@gmail.com" + } + ], + "description": "A library to read, parse and export to PDF SVG files.", + "homepage": "https://github.com/PhenX/php-svg-lib", + "time": "2018-06-03T10:10:03+00:00" + }, + { + "name": "phpoffice/common", + "version": "0.2.9", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/Common.git", + "reference": "edb5d32b1e3400a35a5c91e2539ed6f6ce925e4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/Common/zipball/edb5d32b1e3400a35a5c91e2539ed6f6ce925e4d", + "reference": "edb5d32b1e3400a35a5c91e2539ed6f6ce925e4d", + "shasum": "" + }, + "require": { + "pclzip/pclzip": "^2.8", + "php": ">=5.3.0" + }, + "require-dev": { + "phpdocumentor/phpdocumentor": "2.*", + "phploc/phploc": "2.*", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.36 || ^7.0", + "sebastian/phpcpd": "2.*", + "squizlabs/php_codesniffer": "2.*" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpOffice\\Common\\": "src/Common/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL" + ], + "authors": [ + { + "name": "Mark Baker" + }, + { + "name": "Franck Lefevre", + "homepage": "http://rootslabs.net" + } + ], + "description": "PHPOffice Common", + "homepage": "http://phpoffice.github.io", + "keywords": [ + "common", + "component", + "office", + "php" + ], + "time": "2018-07-13T14:12:34+00:00" + }, + { + "name": "phpoffice/phpword", + "version": "0.15.0", + "source": { + "type": "git", + "url": "https://github.com/PHPOffice/PHPWord.git", + "reference": "dfa2f36cad2b632b7ab1c56473e4f5db9a7caf7f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPOffice/PHPWord/zipball/dfa2f36cad2b632b7ab1c56473e4f5db9a7caf7f", + "reference": "dfa2f36cad2b632b7ab1c56473e4f5db9a7caf7f", + "shasum": "" + }, + "require": { + "ext-xml": "*", + "php": "^5.3.3 || ^7.0", + "phpoffice/common": "^0.2.9", + "zendframework/zend-escaper": "^2.2" + }, + "require-dev": { + "dompdf/dompdf": "0.8.*", + "ext-gd": "*", + "ext-zip": "*", + "friendsofphp/php-cs-fixer": "^2.2", + "mpdf/mpdf": "5.7.4 || 6.* || 7.*", + "php-coveralls/php-coveralls": "1.1.0 || ^2.0", + "phploc/phploc": "2.* || 3.* || 4.*", + "phpmd/phpmd": "2.*", + "phpunit/phpunit": "^4.8.36 || ^7.0", + "squizlabs/php_codesniffer": "^2.9", + "tecnickcom/tcpdf": "6.*" + }, + "suggest": { + "dompdf/dompdf": "Allows writing PDF", + "ext-gd2": "Allows adding images", + "ext-xmlwriter": "Allows writing OOXML and ODF", + "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template", + "ext-zip": "Allows writing OOXML and ODF" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-develop": "0.16-dev" + } + }, + "autoload": { + "psr-4": { + "PhpOffice\\PhpWord\\": "src/PhpWord" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Mark Baker" + }, + { + "name": "Gabriel Bull", + "email": "me@gabrielbull.com", + "homepage": "http://gabrielbull.com/" + }, + { + "name": "Ivan Lanin", + "homepage": "http://ivan.lanin.org" + }, + { + "name": "Roman Syroeshko", + "homepage": "http://ru.linkedin.com/pub/roman-syroeshko/34/a53/994/" + }, + { + "name": "Franck Lefevre", + "homepage": "https://rootslabs.net/blog/" + }, + { + "name": "Antoine de Troostembergh" + } + ], + "description": "PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)", + "homepage": "http://phpoffice.github.io", + "keywords": [ + "ISO IEC 29500", + "OOXML", + "Office Open XML", + "OpenDocument", + "OpenXML", + "PhpOffice", + "PhpWord", + "Rich Text Format", + "WordprocessingML", + "doc", + "docx", + "html", + "odf", + "odt", + "office", + "pdf", + "php", + "reader", + "rtf", + "template", + "template processor", + "word", + "writer" + ], + "time": "2018-07-14T16:59:43+00:00" + }, { "name": "psr/http-message", "version": "1.0.1", @@ -296,6 +636,50 @@ ], "time": "2016-08-06T14:39:51+00:00" }, + { + "name": "sabberworm/php-css-parser", + "version": "8.1.0", + "source": { + "type": "git", + "url": "https://github.com/sabberworm/PHP-CSS-Parser.git", + "reference": "850cbbcbe7fbb155387a151ea562897a67e242ef" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sabberworm/PHP-CSS-Parser/zipball/850cbbcbe7fbb155387a151ea562897a67e242ef", + "reference": "850cbbcbe7fbb155387a151ea562897a67e242ef", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "type": "library", + "autoload": { + "psr-0": { + "Sabberworm\\CSS": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Raphael Schweikert" + } + ], + "description": "Parser for CSS Files written in PHP", + "homepage": "http://www.sabberworm.com/blog/2010/6/10/php-css-parser", + "keywords": [ + "css", + "parser", + "stylesheet" + ], + "time": "2016-07-19T19:14:21+00:00" + }, { "name": "stripe/stripe-php", "version": "v6.24.0", @@ -350,6 +734,51 @@ "stripe" ], "time": "2018-11-28T16:32:29+00:00" + }, + { + "name": "zendframework/zend-escaper", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/zendframework/zend-escaper.git", + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/zendframework/zend-escaper/zipball/31d8aafae982f9568287cb4dce987e6aff8fd074", + "reference": "31d8aafae982f9568287cb4dce987e6aff8fd074", + "shasum": "" + }, + "require": { + "php": "^5.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2", + "zendframework/zend-coding-standard": "~1.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.6.x-dev", + "dev-develop": "2.7.x-dev" + } + }, + "autoload": { + "psr-4": { + "Zend\\Escaper\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", + "keywords": [ + "ZendFramework", + "escaper", + "zf" + ], + "time": "2018-04-25T15:48:53+00:00" } ], "packages-dev": [], diff --git a/langs/en/messages.json b/langs/en/messages.json index 2ed8270..ff489f1 100644 --- a/langs/en/messages.json +++ b/langs/en/messages.json @@ -7,5 +7,6 @@ "This action cannot be undone! All information about this family, including payment history, will be purged forever.": "This action cannot be undone! All information about this family, including payment history, will be purged forever.", "To remove a child, delete the contents of the Name box.": "To remove a child, delete the contents of the Name box.", "No interests selected.": "No interests selected.", - "Events updated.": "Events updated." + "Events updated.": "Events updated.", + "You agree to use the information in this directory for homeschool use ONLY. All other purposes, such as soliciting, is strictly prohibited.": "You agree to use the information in this directory for homeschool use ONLY. All other purposes, such as soliciting, is strictly prohibited." } diff --git a/lib/mkmemberdirectory.php b/lib/mkmemberdirectory.php new file mode 100644 index 0000000..12154b8 --- /dev/null +++ b/lib/mkmemberdirectory.php @@ -0,0 +1,227 @@ +hasPermission("HACHEPORTAL_VIEW")) { + header("Location: ../app.php?msg=no_permission"); + die(); +} + +use Dompdf\Dompdf; + +// Load all families +$familylist = $database->select("families", "familyid", ["ORDER" => ["familyname"]]); +$families = []; +foreach ($familylist as $f) { + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); + $families[] = (new Family())->load($f); +} + +$format = "html"; +if (!empty($_GET["format"])) { + $format = $_GET["format"]; +} + +$date = date("F j Y"); + +if ($format == "html") { + + $icons = ".grad { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMjMwNCIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMjMwNCAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNzc0IDgzNmwxOCAzMTZxNCA2OS04MiAxMjh0LTIzNSA5My41LTMyMyAzNC41LTMyMy0zNC41LTIzNS05My41LTgyLTEyOGwxOC0zMTYgNTc0IDE4MXEyMiA3IDQ4IDd0NDgtN3ptNTMwLTMyNHEwIDIzLTIyIDMxbC0xMTIwIDM1MnEtNCAxLTEwIDF0LTEwLTFsLTY1Mi0yMDZxLTQzIDM0LTcxIDExMS41dC0zNCAxNzguNXE2MyAzNiA2MyAxMDkgMCA2OS01OCAxMDdsNTggNDMzcTIgMTQtOCAyNS05IDExLTI0IDExaC0xOTJxLTE1IDAtMjQtMTEtMTAtMTEtOC0yNWw1OC00MzNxLTU4LTM4LTU4LTEwNyAwLTczIDY1LTExMSAxMS0yMDcgOTgtMzMwbC0zMzMtMTA0cS0yMi04LTIyLTMxdDIyLTMxbDExMjAtMzUycTQtMSAxMC0xdDEwIDFsMTEyMCAzNTJxMjIgOCAyMiAzMXoiLz48L3N2Zz4='); + } + .phone { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjAwIDEyNDBxMCAyNy0xMCA3MC41dC0yMSA2OC41cS0yMSA1MC0xMjIgMTA2LTk0IDUxLTE4NiA1MS0yNyAwLTUzLTMuNXQtNTcuNS0xMi41LTQ3LTE0LjUtNTUuNS0yMC41LTQ5LTE4cS05OC0zNS0xNzUtODMtMTI3LTc5LTI2NC0yMTZ0LTIxNi0yNjRxLTQ4LTc3LTgzLTE3NS0zLTktMTgtNDl0LTIwLjUtNTUuNS0xNC41LTQ3LTEyLjUtNTcuNS0zLjUtNTNxMC05MiA1MS0xODYgNTYtMTAxIDEwNi0xMjIgMjUtMTEgNjguNS0yMXQ3MC41LTEwcTE0IDAgMjEgMyAxOCA2IDUzIDc2IDExIDE5IDMwIDU0dDM1IDYzLjUgMzEgNTMuNXEzIDQgMTcuNSAyNXQyMS41IDM1LjUgNyAyOC41cTAgMjAtMjguNSA1MHQtNjIgNTUtNjIgNTMtMjguNSA0NnEwIDkgNSAyMi41dDguNSAyMC41IDE0IDI0IDExLjUgMTlxNzYgMTM3IDE3NCAyMzV0MjM1IDE3NHEyIDEgMTkgMTEuNXQyNCAxNCAyMC41IDguNSAyMi41IDVxMTggMCA0Ni0yOC41dDUzLTYyIDU1LTYyIDUwLTI4LjVxMTQgMCAyOC41IDd0MzUuNSAyMS41IDI1IDE3LjVxMjUgMTUgNTMuNSAzMXQ2My41IDM1IDU0IDMwcTcwIDM1IDc2IDUzIDMgNyAzIDIxeiIvPjwvc3ZnPg=='); + } + .email { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xNjY0IDE1MDR2LTc2OHEtMzIgMzYtNjkgNjYtMjY4IDIwNi00MjYgMzM4LTUxIDQzLTgzIDY3dC04Ni41IDQ4LjUtMTAyLjUgMjQuNWgtMnEtNDggMC0xMDIuNS0yNC41dC04Ni41LTQ4LjUtODMtNjdxLTE1OC0xMzItNDI2LTMzOC0zNy0zMC02OS02NnY3NjhxMCAxMyA5LjUgMjIuNXQyMi41IDkuNWgxNDcycTEzIDAgMjIuNS05LjV0OS41LTIyLjV6bTAtMTA1MXYtMjQuNWwtLjUtMTMtMy0xMi41LTUuNS05LTktNy41LTE0LTIuNWgtMTQ3MnEtMTMgMC0yMi41IDkuNXQtOS41IDIyLjVxMCAxNjggMTQ3IDI4NCAxOTMgMTUyIDQwMSAzMTcgNiA1IDM1IDI5LjV0NDYgMzcuNSA0NC41IDMxLjUgNTAuNSAyNy41IDQzIDloMnEyMCAwIDQzLTl0NTAuNS0yNy41IDQ0LjUtMzEuNSA0Ni0zNy41IDM1LTI5LjVxMjA4LTE2NSA0MDEtMzE3IDU0LTQzIDEwMC41LTExNS41dDQ2LjUtMTMxLjV6bTEyOC0zN3YxMDg4cTAgNjYtNDcgMTEzdC0xMTMgNDdoLTE0NzJxLTY2IDAtMTEzLTQ3dC00Ny0xMTN2LTEwODhxMC02NiA0Ny0xMTN0MTEzLTQ3aDE0NzJxNjYgMCAxMTMgNDd0NDcgMTEzeiIvPjwvc3ZnPg=='); + } + .mapmarker { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPHN2ZyB3aWR0aD0iMTc5MiIgaGVpZ2h0PSIxNzkyIiB2aWV3Qm94PSIwIDAgMTc5MiAxNzkyIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjxwYXRoIGQ9Ik0xMTUyIDY0MHEwLTEwNi03NS0xODF0LTE4MS03NS0xODEgNzUtNzUgMTgxIDc1IDE4MSAxODEgNzUgMTgxLTc1IDc1LTE4MXptMjU2IDBxMCAxMDktMzMgMTc5bC0zNjQgNzc0cS0xNiAzMy00Ny41IDUydC02Ny41IDE5LTY3LjUtMTktNDYuNS01MmwtMzY1LTc3NHEtMzMtNzAtMzMtMTc5IDAtMjEyIDE1MC0zNjJ0MzYyLTE1MCAzNjIgMTUwIDE1MCAzNjJ6Ii8+PC9zdmc+'); + } + .nocamera { + background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcKICAgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIgogICB4bWxuczpjYz0iaHR0cDovL2NyZWF0aXZlY29tbW9ucy5vcmcvbnMjIgogICB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiCiAgIHhtbG5zOnN2Zz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciCiAgIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIKICAgeG1sbnM6c29kaXBvZGk9Imh0dHA6Ly9zb2RpcG9kaS5zb3VyY2Vmb3JnZS5uZXQvRFREL3NvZGlwb2RpLTAuZHRkIgogICB4bWxuczppbmtzY2FwZT0iaHR0cDovL3d3dy5pbmtzY2FwZS5vcmcvbmFtZXNwYWNlcy9pbmtzY2FwZSIKICAgd2lkdGg9IjEwOTYuNTEwNyIKICAgaGVpZ2h0PSIxMDk2LjUxMDYiCiAgIHZpZXdCb3g9IjAgMCAxMDk2LjUxMDcgMTA5Ni41MTA2IgogICB2ZXJzaW9uPSIxLjEiCiAgIGlkPSJzdmc5MDUiCiAgIHNvZGlwb2RpOmRvY25hbWU9Im5vLWNhbWVyYS5zdmciCiAgIGlua3NjYXBlOnZlcnNpb249IjAuOTIuMyAoMjQwNTU0NiwgMjAxOC0wMy0xMSkiCiAgIGlua3NjYXBlOmV4cG9ydC1maWxlbmFtZT0iL2hvbWUvc2t5bGFyL0RvY3VtZW50cy9Bc3NldHMvR3JhcGhpY3Mvbm8tY2FtZXJhLnBuZyIKICAgaW5rc2NhcGU6ZXhwb3J0LXhkcGk9IjEuNDAwODA3MyIKICAgaW5rc2NhcGU6ZXhwb3J0LXlkcGk9IjEuNDAwODA3MyI+CiAgPG1ldGFkYXRhCiAgICAgaWQ9Im1ldGFkYXRhOTExIj4KICAgIDxyZGY6UkRGPgogICAgICA8Y2M6V29yawogICAgICAgICByZGY6YWJvdXQ9IiI+CiAgICAgICAgPGRjOmZvcm1hdD5pbWFnZS9zdmcreG1sPC9kYzpmb3JtYXQ+CiAgICAgICAgPGRjOnR5cGUKICAgICAgICAgICByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIiAvPgogICAgICAgIDxkYzp0aXRsZT48L2RjOnRpdGxlPgogICAgICA8L2NjOldvcms+CiAgICA8L3JkZjpSREY+CiAgPC9tZXRhZGF0YT4KICA8ZGVmcwogICAgIGlkPSJkZWZzOTA5IiAvPgogIDxzb2RpcG9kaTpuYW1lZHZpZXcKICAgICBwYWdlY29sb3I9IiNmZmZmZmYiCiAgICAgYm9yZGVyY29sb3I9IiM2NjY2NjYiCiAgICAgYm9yZGVyb3BhY2l0eT0iMSIKICAgICBvYmplY3R0b2xlcmFuY2U9IjEwIgogICAgIGdyaWR0b2xlcmFuY2U9IjEwIgogICAgIGd1aWRldG9sZXJhbmNlPSIxMCIKICAgICBpbmtzY2FwZTpwYWdlb3BhY2l0eT0iMCIKICAgICBpbmtzY2FwZTpwYWdlc2hhZG93PSIyIgogICAgIGlua3NjYXBlOndpbmRvdy13aWR0aD0iMTkyMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctaGVpZ2h0PSIxMDExIgogICAgIGlkPSJuYW1lZHZpZXc5MDciCiAgICAgc2hvd2dyaWQ9ImZhbHNlIgogICAgIGlua3NjYXBlOnpvb209IjAuMjA5ODIxNDMiCiAgICAgaW5rc2NhcGU6Y3g9Ii0yNjIuODIyNTUiCiAgICAgaW5rc2NhcGU6Y3k9IjQ4OC43NDczNSIKICAgICBpbmtzY2FwZTp3aW5kb3cteD0iMTkyMCIKICAgICBpbmtzY2FwZTp3aW5kb3cteT0iMCIKICAgICBpbmtzY2FwZTp3aW5kb3ctbWF4aW1pemVkPSIxIgogICAgIGlua3NjYXBlOmN1cnJlbnQtbGF5ZXI9InN2ZzkwNSIKICAgICBmaXQtbWFyZ2luLXRvcD0iMCIKICAgICBmaXQtbWFyZ2luLWxlZnQ9IjAiCiAgICAgZml0LW1hcmdpbi1yaWdodD0iMCIKICAgICBmaXQtbWFyZ2luLWJvdHRvbT0iMCIgLz4KICA8cGF0aAogICAgIHN0eWxlPSJzdHJva2Utd2lkdGg6Mi4yMTA3MDY5NSIKICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgIGQ9Ik0gNTQ4LjI1NTI4LDAgQyAyNDUuNDYzNiwwIDAsMjQ1LjQ2MTQzIDAsNTQ4LjI1NTMzIGMgMCwzMDIuNzkzODggMjQ1LjQ2MzYsNTQ4LjI1NTI3IDU0OC4yNTUyOCw1NDguMjU1MjcgMzAyLjc5MTgsMCA1NDguMjU1NTIsLTI0NS40NjM1OSA1NDguMjU1NTIsLTU0OC4yNTUyNyBDIDEwOTYuNTEwOCwyNDUuNDYzNjQgODUxLjA0OTI4LDAgNTQ4LjI1NTI4LDAgWiBtIDI4Ny42MzA4LDI2MC42MjQ2NyBjIDE0NC42ODYzLDE0NC42ODYzNyAxNTQuNzQ5NSwzNjUuODMwMDcgNDUuNzEwOCw1MjAuOTI0MzQgTCAzMTQuOTU5NDEsMjE0LjkxNjA5IGMgMTU1LjIwMDQsLTEwOS4xMTE2NSAzNzYuMzE5ODcsLTk4Ljg5NTk4IDUyMC45MjY2Nyw0NS43MDg1OCB6IE0gMjYwLjYyNDYsODM1Ljg4NTkxIEMgMTE1LjkzODMsNjkxLjE5OTYxIDEwNS44NzUyLDQ3MC4wNTYwMyAyMTQuOTEzOCwzMTQuOTYxNjQgbCA1NjYuNjM3NDgsNTY2LjYzMjk3IGMgLTE1NS4xOTgzLDEwOS4xMTE2IC0zNzYuMzE5ODcsOTguODk4MSAtNTIwLjkyNjY4LC00NS43MDg3IHoiCiAgICAgaWQ9InBhdGgxMDQxIiAvPgogIDxwYXRoCiAgICAgZD0ibSA1NDguMjU1MzgsNDg5LjkyOTA2IHEgNDMuMzgwMSwwIDc0LjE4MzcsMzAuODAzNTUgMzAuODAzNSwzMC44MDM1NCAzMC44MDM1LDc0LjE4MzY5IDAsNDMuMzgwMTUgLTMwLjgwMzUsNzQuMTgzNzEgLTMwLjgwMzYsMzAuODAzNSAtNzQuMTgzNywzMC44MDM1IC00My4zODAxNywwIC03NC4xODM2NywtMzAuODAzNSAtMzAuODAzNTUsLTMwLjgwMzU2IC0zMC44MDM1NSwtNzQuMTgzNzEgMCwtNDMuMzgwMTUgMzAuODAzNTUsLTc0LjE4MzY5IDMwLjgwMzUsLTMwLjgwMzU1IDc0LjE4MzY3LC0zMC44MDM1NSB6IG0gMjU2LjYzNTUsLTE1MS42NDgyMyBxIDM4LjY0MTEsMCA2NS45ODE1LDI3LjM0MDQyIDI3LjM0MDQsMjcuMzQwNDMgMjcuMzQwNCw2NS45ODE1NyB2IDMyNi42MjY5OSBxIDAsMzguNjQxMSAtMjcuMzQwNCw2NS45ODE2IC0yNy4zNDA0LDI3LjM0MDQgLTY1Ljk4MTUsMjcuMzQwNCBIIDI5MS42MTk5MyBxIC0zOC42NDExOCwwIC02NS45ODE1OCwtMjcuMzQwNCAtMjcuMzQwNCwtMjcuMzQwNSAtMjcuMzQwNCwtNjUuOTgxNiBWIDQzMS42MDI4MiBxIDAsLTM4LjY0MTEzIDI3LjM0MDQsLTY1Ljk4MTU3IDI3LjM0MDQsLTI3LjM0MDQyIDY1Ljk4MTU4LC0yNy4zNDA0MiBoIDgxLjY1Njc0IGwgMTguNTkxNDksLTQ5LjU3NzMxIHEgNi45MjYyNCwtMTcuODYyNDEgMjUuMzM1NDYsLTMwLjgwMzU0IDE4LjQwOTIyLC0xMi45NDExNCAzNy43Mjk3OSwtMTIuOTQxMTQgaCAxODYuNjQzOTcgcSAxOS4zMjA1LDAgMzcuNzI5OCwxMi45NDExNCAxOC40MDkyLDEyLjk0MTEzIDI1LjMzNTQsMzAuODAzNTQgbCAxOC41OTE1LDQ5LjU3NzMxIHogbSAtMjU2LjYzNTUsNDE5Ljk0ODk4IHEgNjcuNDM5NywwIDExNS4zNzY2LC00Ny45MzY5IDQ3LjkzNjksLTQ3LjkzNjkgNDcuOTM2OSwtMTE1LjM3NjYgMCwtNjcuNDM5NzIgLTQ3LjkzNjksLTExNS4zNzY2IC00Ny45MzY5LC00Ny45MzY4OCAtMTE1LjM3NjYsLTQ3LjkzNjg4IC02Ny40Mzk3LDAgLTExNS4zNzY1OCw0Ny45MzY4OCAtNDcuOTM2ODgsNDcuOTM2ODggLTQ3LjkzNjg4LDExNS4zNzY2IDAsNjcuNDM5NyA0Ny45MzY4OCwxMTUuMzc2NiA0Ny45MzY4OCw0Ny45MzY5IDExNS4zNzY1OCw0Ny45MzY5IHoiCiAgICAgaWQ9InBhdGg5MDMiCiAgICAgaW5rc2NhcGU6Y29ubmVjdG9yLWN1cnZhdHVyZT0iMCIKICAgICBzdHlsZT0ic3Ryb2tlLXdpZHRoOjAuMzY0NTM5MDMiIC8+CiAgPHBhdGgKICAgICBpbmtzY2FwZTpjb25uZWN0b3ItY3VydmF0dXJlPSIwIgogICAgIHN0eWxlPSJmaWxsOiNmZmZmZmY7ZmlsbC1vcGFjaXR5OjE7c3Ryb2tlLXdpZHRoOjIuMjEwNzA2OTUiCiAgICAgZD0ibSAzOTEuMDE3MDgsMjY3Ljk2NjI2IC0xNy43NDAyLDQ3LjMwNjYgaCAtODEuNjU2MyBjIC0xNS43ODY4LDAgLTMwLjE1NzcsMy40MjgyIC00My4xMTUyLDEwLjI3MzQgbCAxNjAuNTQzLDE2MC41NDExIGMgNi41OTM2LC0xMC40MDExIDE0LjUzMDEsLTIwLjI1NDcgMjMuODMwMSwtMjkuNTU0NyAyOC4xMjA4LC0yOC4xMjA5IDYxLjI3ODgsLTQzLjg2MzkgOTkuNDY2NywtNDcuMjQwMyB6IG0gMTU3LjIzODMsMTk4Ljk1NSBjIC0yOC45MjAxLDAgLTUzLjY0NzksMTAuMjY3MSAtNzQuMTgzNiwzMC44MDI4IC05LjU1NTgsOS41NTU4IC0xNi44ODQ5LDIwLjAyMTMgLTIxLjk5NDEsMzEuMzkyNiBsIDEzOC45NzA3LDEzOC45Njg3NSBjIDExLjM3MDQsLTUuMTA5MyAyMS44MzU0LC0xMi40MzkxIDMxLjM5MDYsLTIxLjk5NDE1IDIwLjUzNTcsLTIwLjUzNTcgMzAuODAyNywtNDUuMjYzNSAzMC44MDI3LC03NC4xODM2IDAsLTIzLjI3NTYgLTYuNjU1MiwtNDMuODMzMSAtMTkuOTU3LC02MS42Nzc4IGwgLTIzLjM0NzcsLTIzLjM0NTcgYyAtMTcuODQ1NywtMTMuMzA0MSAtMzguNDA0MSwtMTkuOTYyOSAtNjEuNjgxNiwtMTkuOTYyOSB6IG0gMTYyLjYxNzIsMTIwLjg5NjUgYyAtMy4zNzYsMzguMTg4OSAtMTkuMTE4OSw3MS4zNDU0NSAtNDcuMjQwMiw5OS40NjY4NSAtOS4yOTk2LDkuMjk5NSAtMTkuMTU0MiwxNy4yMzY3IC0yOS41NTQ3LDIzLjgzMDEgbCAxMTcuNDMxNiwxMTcuNDI5NiBoIDUzLjM4MDkgYyAyNS43NjA3LDAgNDcuNzU1NSwtOS4xMTI5IDY1Ljk4MjQsLTI3LjMzOTggMTguMjI2OSwtMTguMjI3MSAyNy4zMzk4LC00MC4yMjE4IDI3LjMzOTgsLTY1Ljk4MjUgdiAtMi40MDA0IGMgLTUuMTk1OSw4Ljc0NzcgLTEwLjcyMDcsMTcuMzM0NiAtMTYuNjE1MiwyNS43MTg5IHogbSAtNTEyLjU3NDIsMTQ1LjExMzM1IHYgMi4yOTEgYyAwLDI1Ljc2MDcgOS4xMTI5LDQ3Ljc1NTQgMjcuMzM5OCw2NS45ODI0IDE0LjM4MTMsMTQuMzgxMyAzMS4xMTAyLDIzLjA4MyA1MC4xODE3LDI2LjExNzIgLTUuMTUwNywtNC42NTc3IC0xMC4yMjAxLC05LjQ2OCAtMTUuMTk1MywtMTQuNDQzMyAtMjQuNjYyNCwtMjQuNjYyNCAtNDUuNDA5OCwtNTEuNTQ3OCAtNjIuMzI2MiwtNzkuOTQ3MyB6IgogICAgIGlkPSJwYXRoMTA0MS0zIiAvPgo8L3N2Zz4K'); + }"; + + + $htmltop = << +HACHE Member Directory + +

HACHE Member Directory

+

+ Updated: $date +
+ Icon key: + : Graduated student | : Photo permission denied +
+ You agree to use the information in this directory for homeschool use ONLY. All other purposes, such as soliciting, is strictly prohibited. +

+ +
+END; + + $htmlmiddle = ""; + + $currentletter = " "; + + foreach ($families as $f) { + // Add headings for letters + if (strtoupper($f->getName()[0]) > $currentletter) { + $currentletter = strtoupper($f->getName()[0]); + $htmlmiddle .= "\n

$currentletter

\n"; + } + $famhtml = "\n
\n" + . "\t" . $f->getName() . ", " . $f->getFather() . " and " . $f->getMother() . "\n"; + if (!$f->getPhotoPermission()) { + $famhtml .= "\t\n"; + } + $famhtml .= "\t
" . $f->getAddress() . ", " . $f->getCity() . ", " . $f->getState() . " " . $f->getZip() . "\n" + . "\t
getPhone() . "\">" . $f->getPhone() . "    getEmail() . "\">" . $f->getEmail() . "\n"; + foreach ($f->getChildren() as $child) { + $famhtml .= "\t
\n"; + if ($child->isGraduated()) { + $famhtml .= "\t\t\n"; + } else { + $famhtml .= "\t\t\n"; + } + $famhtml .= "\t\t" . $child->getName() . ", " . date("M y", $child->getBirthday()) . "\n"; + $famhtml .= "\t
\n"; + } + $famhtml .= "
\n"; + $htmlmiddle .= $famhtml; + } + + $htmlbottom = << +END; + + $html = $htmltop . $htmlmiddle . $htmlbottom; + + header("Content-Type: text/html; charset=UTF-8"); + header("Content-disposition: attachment; filename=\"HACHE_Directory_" . date("Y-m-d") . ".html\""); + echo $html; +} else { + \PhpOffice\PhpWord\Settings::setOutputEscapingEnabled(true); + $phpWord = new \PhpOffice\PhpWord\PhpWord(); + + $properties = $phpWord->getDocInfo(); + $properties->setCreator('HACHE Membership Portal'); + $properties->setCompany('HACHE'); + $properties->setTitle('HACHE Member Directory'); + $paperSize = new \PhpOffice\PhpWord\Style\Paper(); + $paperSize->setSize("Letter"); + + $phpWord->addTitleStyle(1, ['bold' => true, 'size' => 24, 'alignment' => \PhpOffice\PhpWord\SimpleType\Jc::CENTER]); + $phpWord->addTitleStyle(2, ['bold' => true, 'size' => 16]); + + $header = $phpWord->addSection(["paperSize" => "Letter", 'marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600]); + $header->addTitle("HACHE Member Directory\n", 1); + $updated = $header->addTextRun(); + $updated->addText("Updated: ", ['bold' => true]); + $updated->addText("$date"); + $iconkey = $header->addTextRun(); + $iconkey->addText("Icon key: ", ['bold' => true]); + $iconkey->addText("◊: Graduated student | ►: Photo permission denied"); + $header->addText($Strings->get("You agree to use the information in this directory for homeschool use ONLY. All other purposes, such as soliciting, is strictly prohibited.", false)); + + $header->addTextBreak(2); + + $body = $phpWord->addSection(['breakType' => 'continuous', 'colsNum' => 2, "paperSize" => "Letter", 'marginLeft' => 600, 'marginRight' => 600, 'marginTop' => 600, 'marginBottom' => 600]); + + $currentletter = " "; + + foreach ($families as $f) { + // Add headings for letters + if (strtoupper($f->getName()[0]) > $currentletter) { + $currentletter = strtoupper($f->getName()[0]); + $body->addTitle("$currentletter", 2); + } + $famtext = $body->addTextRun(); + if (!$f->getPhotoPermission()) { + $famtext->addText("►"); + } + $famtext->addText($f->getName(), ['bold' => true]); + $famtext->addText(", " . $f->getFather() . " and " . $f->getMother()); + $body->addText($f->getAddress() . ", " . $f->getCity() . ", " . $f->getState() . " " . $f->getZip()); + $links = $body->addTextRun(); + $links->addLink("tel:" . $f->getPhone(), $f->getPhone()); + $links->addText(" "); + $links->addLink("mailto:" . $f->getEmail(), $f->getEmail()); + + foreach ($f->getChildren() as $child) { + $chtext = $body->addTextRun(["indent" => 1440]); + if ($child->isGraduated()) { + $chtext->addText(" ●"); + } else { + $chtext->addText(" "); + } + $chtext->addText($child->getName() . ", " . date("M y", $child->getBirthday())); + } + $body->addTextBreak(1); + } + + header("Content-Description: File Transfer"); + header('Content-Transfer-Encoding: binary'); + header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); + header('Expires: 0'); + + switch ($format) { + case "docx": + $phpWord->getCompatibility()->setOoxmlVersion(15); + $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'Word2007'); + header("Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document"); + header("Content-disposition: attachment; filename=\"HACHE_Directory_" . date("Y-m-d") . ".docx\""); + break; + case "odt": + default: + $objWriter = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'ODText'); + header("Content-Type: application/vnd.oasis.opendocument.text"); + header("Content-disposition: attachment; filename=\"HACHE_Directory_" . date("Y-m-d") . ".odt\""); + break; + } + $objWriter->save('php://output'); +} +?> \ No newline at end of file diff --git a/static/img/export/child.png b/static/img/export/child.png new file mode 100644 index 0000000000000000000000000000000000000000..f541d09f332bbe967ad3a3e3887247a23fed8413 GIT binary patch literal 331 zcmV-R0kr;!P)yUGTs6Qcbw)L12-U-x&g_z!sAM~ z3K5x_g%$uKpr@Jd$-7no7Qh8amEOFeZz^l&rckOfUR%5p;{p03xKbQJD81!;<^qsb zLQ0540@d(D6P}BQwRDChLhA#~&(_b$R35+sxB|?ieg@zy58wf80FIS$_1Q=r3xFNa2R0PHTYI1joPjBD dvhe(4JpsKvWZ@Ym0^R@s002ovPDHLkV1frDgKhu- literal 0 HcmV?d00001 diff --git a/static/img/export/empty.png b/static/img/export/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..a61cda2551179a2f512e6c307c2aa55d39be2969 GIT binary patch literal 157 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmSQK*5Dp-y;YjHK@;M7UB8wRq z_>O=u<5X=vX`rBFiEBhjaDG}zd16s2LwR|*US?i)adKios$PCk`s{Z$Qb0vgo-U3d q5v^|zGBN^rO$z_l=Xp4QnD5yH6c`xY85e-eXYh3Ob6Mw<&;$U1uqHnM literal 0 HcmV?d00001 diff --git a/static/img/export/graduation-cap.png b/static/img/export/graduation-cap.png new file mode 100644 index 0000000000000000000000000000000000000000..d0211efca679a60bd7e009e4644c3b5c01568bf4 GIT binary patch literal 550 zcmV+>0@?kEP)#thH+fL&Q?S04uQw9m;;ez%b3I!?5hf~ z7egV?&k7J(_8U{Ujsryy^)PV?e_IHVXKyf!qe+lqOt%Rj&!%ys7CIYJ$u0Y19k(n^ zlfmJ$))w_IJi|3j6!of(1n2KKh#p+Tglflr2~TiI^a&}gTOrWhl;65>77spj(RUndj9)g|;{ZZUTAG#9rx^My`co%F0CsXG2g&3n%fEEJK{?LCV&it$RO4yMT zW2^XznNRq?EDLj5e8N^&Xh!sDyK2%vF=KBTmVL{EsdY8jWyIt_@k8Ay!R@fa)0ugVG@ zg&2j}+|WOi(Vi7$cU5%yj^S|llV0(wa7px9oW*Orz*GEa1}04p#F^c%8e}bMtf6{F oyKUO=K*@`6dpkio>Zn!v4|DxJcP{G5HUIzs07*qoM6N<$g46W(DgXcg literal 0 HcmV?d00001 diff --git a/static/img/export/no-camera.png b/static/img/export/no-camera.png new file mode 100644 index 0000000000000000000000000000000000000000..fd82b1e0341338dc8070ce4ce9864185227fa8a9 GIT binary patch literal 1135 zcmV-#1d#iQP)~xUWD+H1fB(kfG2^+fi`#T4p0R0z_-8`z*ZC3 zfpQGE1l$EAq}~NS1iJ3UaU8e+{L_SEU3Y==fYq$?F5t#JIM#Imc+})5VzBiBUjs)B zYdgS~z*U#v7VsDF81Mw}3~&mF8TQ^p)zB~g=T;|o3@6wI-T)p7+U!ajaL(PM$MFbUGbG z;I@09P9WvtchFc9@9a5G(%58P2Tnwz(c8IPPIPe`M?yqmPm90_AgkF+ZghBFTlgDw zXV(F-EKBC+=Zz$6+YU=&4S2-G_S(k)KG2Mx0zF=vP9m4f$-uyXw6wJR1bhOlgdoua zT+wXr16mAUSryi0P3Dk&Cbp?)Wpil zii47m0|?lLdTStXJb=I`Ks+Ab)C;p(tx7VPJOi8#AkbqXpr_zu0D&Q(1*qzUxwf_@ zKy7kz@`_KN@J+#wnsF+Czzc4eucO_LiHQjTWNvQGuUYj2FKf01fQy>(vj76$xdfiV z(A#3*pKx3{;pv9Zz6tUM$# zs0qo7bsAJVEO{4Fsnli5vit}Ls(E$rpLDjiwqEn=n0fi(+b-aPAsioezbzYZ{y>|AOk;Tu>enh|Sla=<0=@x$1^xu?0}cV* zs4jX6bIMjxWBH8`hu{eCz2OA^SAQU29QTtLYI?2f5l!k2@FoE{4