mirror of
https://github.com/standardebooks/web.git
synced 2025-07-05 14:20:29 -04:00
Use a NOW constant instead of new DateTimeImmutable objects, and tweak how some donation drive dates work
This commit is contained in:
parent
376dacd833
commit
eec79712fc
27 changed files with 108 additions and 143 deletions
|
@ -87,9 +87,7 @@ class Artist{
|
|||
* @throws Exceptions\InvalidArtistException
|
||||
*/
|
||||
public function Validate(): void{
|
||||
/** @throws void */
|
||||
$now = new DateTimeImmutable();
|
||||
$thisYear = intval($now->format('Y'));
|
||||
$thisYear = intval(NOW->format('Y'));
|
||||
|
||||
$error = new Exceptions\InvalidArtistException();
|
||||
|
||||
|
|
|
@ -330,9 +330,7 @@ class Artwork{
|
|||
* @throws Exceptions\InvalidArtworkException
|
||||
*/
|
||||
protected function Validate(?string $imagePath = null, bool $isImageRequired = true): void{
|
||||
/** @throws void */
|
||||
$now = new DateTimeImmutable();
|
||||
$thisYear = intval($now->format('Y'));
|
||||
$thisYear = intval(NOW->format('Y'));
|
||||
$error = new Exceptions\InvalidArtworkException();
|
||||
|
||||
if($this->Artist === null){
|
||||
|
@ -664,8 +662,7 @@ class Artwork{
|
|||
|
||||
$this->Validate($imagePath, true);
|
||||
|
||||
/** @throws void */
|
||||
$this->Created = new DateTimeImmutable();
|
||||
$this->Created = NOW;
|
||||
|
||||
$tags = [];
|
||||
foreach($this->Tags as $artworkTag){
|
||||
|
@ -731,10 +728,8 @@ class Artwork{
|
|||
if($imagePath !== null){
|
||||
$this->MimeType = ImageMimeType::FromFile($imagePath);
|
||||
|
||||
// Manually set the updated timestamp, because if we only update the image and nothing else, the row's
|
||||
// updated timestamp won't change automatically.
|
||||
/** @throws void */
|
||||
$this->Updated = new DateTimeImmutable();
|
||||
// Manually set the updated timestamp, because if we only update the image and nothing else, the row's updated timestamp won't change automatically.
|
||||
$this->Updated = NOW;
|
||||
$this->_ImageUrl = null;
|
||||
$this->_ThumbUrl = null;
|
||||
$this->_Thumb2xUrl = null;
|
||||
|
@ -751,12 +746,12 @@ class Artwork{
|
|||
$newDeathYear = $this->Artist->DeathYear;
|
||||
$this->Artist = Artist::GetOrCreate($this->Artist);
|
||||
|
||||
// Save the artist death year in case we changed it
|
||||
// Save the artist death year in case we changed it.
|
||||
if($newDeathYear != $this->Artist->DeathYear){
|
||||
Db::Query('UPDATE Artists set DeathYear = ? where ArtistId = ?', [$newDeathYear , $this->Artist->ArtistId]);
|
||||
}
|
||||
|
||||
// Save the artwork
|
||||
// Save the artwork.
|
||||
Db::Query('
|
||||
UPDATE Artworks
|
||||
set
|
||||
|
@ -787,9 +782,8 @@ class Artwork{
|
|||
$this->ArtworkId]
|
||||
);
|
||||
|
||||
// Delete artists who are no longer to attached to an artwork
|
||||
// Don't delete from the ArtistAlternateNames table to prevent accidentally
|
||||
// deleting those manually-added entries.
|
||||
// Delete artists who are no longer to attached to an artwork.
|
||||
// Don't delete from the ArtistAlternateNames table to prevent accidentally deleting those manually-added entries.
|
||||
Db::Query('
|
||||
DELETE
|
||||
from Artists
|
||||
|
@ -797,7 +791,7 @@ class Artwork{
|
|||
(select distinct ArtistId from Artworks)
|
||||
');
|
||||
|
||||
// Update tags for this artwork
|
||||
// Update tags for this artwork.
|
||||
Db::Query('
|
||||
DELETE from ArtworkTags
|
||||
where
|
||||
|
|
|
@ -39,8 +39,7 @@ class AtomFeed extends Feed{
|
|||
// Did we actually update the feed? If so, write to file and update the index
|
||||
if($this->HasChanged($this->Path)){
|
||||
// Files don't match, save the file
|
||||
/** @throws void */
|
||||
$this->Updated = new DateTimeImmutable();
|
||||
$this->Updated = NOW;
|
||||
$this->Save();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
<?
|
||||
// Auto-included by Composer in composer.json to satisfy PHPStan
|
||||
// Auto-included by Composer in composer.json to satisfy PHPStan.
|
||||
use Safe\DateTimeImmutable;
|
||||
use function Safe\define;
|
||||
|
||||
$now = new DateTimeImmutable();
|
||||
$nowPd = new DateTimeImmutable('now', new DateTimeZone('America/Juneau')); // Latest continental US time zone
|
||||
const NOW = new DateTimeImmutable();
|
||||
|
||||
const SITE_STATUS_LIVE = 'live';
|
||||
const SITE_STATUS_DEV = 'dev';
|
||||
|
||||
define('SITE_STATUS', get_cfg_var('app.site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use define() and not const so we can use a function.
|
||||
define('SITE_STATUS', get_cfg_var('app.site_status') ?: SITE_STATUS_DEV); // Set in the PHP INI configuration for both CLI and FPM. Have to use `define()` and not `const` so we can use a function.
|
||||
|
||||
// No trailing slash on any of the below constants.
|
||||
if(SITE_STATUS == SITE_STATUS_LIVE){
|
||||
|
@ -44,7 +43,7 @@ const ARTWORK_IMAGE_MINIMUM_HEIGHT = 300;
|
|||
const CAPTCHA_IMAGE_HEIGHT = 72;
|
||||
const CAPTCHA_IMAGE_WIDTH = 230;
|
||||
|
||||
// These are defined for convenience, so that getting HTTP input isn't so wordy
|
||||
// These are defined for convenience, so that getting HTTP input isn't so wordy.
|
||||
const GET = Enums\HttpVariableSource::Get;
|
||||
const POST = Enums\HttpVariableSource::Post;
|
||||
const SESSION = Enums\HttpVariableSource::Session;
|
||||
|
@ -72,18 +71,18 @@ const ZOHO_WEBHOOK_LOG_FILE_PATH = '/var/log/local/webhooks-zoho.log'; // Must b
|
|||
const DONATIONS_LOG_FILE_PATH = '/var/log/local/donations.log'; // Must be writable by `www-data` Unix user.
|
||||
const ARTWORK_UPLOADS_LOG_FILE_PATH = '/var/log/local/artwork-uploads.log'; // Must be writable by `www-data` Unix user.
|
||||
|
||||
define('PD_YEAR', intval($nowPd->format('Y')) - 96);
|
||||
define('PD_YEAR', intval((new DateTimeImmutable('now', new DateTimeZone('America/Juneau')))->format('Y')) - 96); // Latest continental US time zone.
|
||||
define('PD_STRING', 'January 1, ' . (PD_YEAR + 1));
|
||||
|
||||
define('DONATION_HOLIDAY_ALERT_ON', $now > new DateTimeImmutable('November 15, ' . $now->format('Y')) || $now < new DateTimeImmutable('January 7, ' . $now->add(new DateInterval('P1Y'))->format('Y')));
|
||||
define('DONATION_HOLIDAY_ALERT_ON', NOW > new DateTimeImmutable('November 15, ' . NOW->format('Y')) || NOW < new DateTimeImmutable('January 7, ' . NOW->add(new DateInterval('P1Y'))->format('Y')));
|
||||
define('DONATION_ALERT_ON', DONATION_HOLIDAY_ALERT_ON || rand(1, 4) == 2);
|
||||
|
||||
// Controls the progress bar donation dialog
|
||||
const DONATION_DRIVE_ON = true;
|
||||
const DONATION_DRIVE_START = 'May 20, 2024 00:00:00 America/New_York';
|
||||
const DONATION_DRIVE_END = 'June 3, 2024 23:59:00 America/New_York';
|
||||
const DONATION_DRIVE_START = new DateTimeImmutable('May 20, 2024 00:00:00 America/New_York');
|
||||
const DONATION_DRIVE_END = new DateTimeImmutable('June 3, 2024 23:59:00 America/New_York');
|
||||
|
||||
// Controls the countdown donation dialog
|
||||
const DONATION_DRIVE_COUNTER_ON = false;
|
||||
const DONATION_DRIVE_COUNTER_START = 'May 2, 2022 00:00:00 America/New_York';
|
||||
const DONATION_DRIVE_COUNTER_END = 'May 8, 2022 23:59:00 America/New_York';
|
||||
const DONATION_DRIVE_COUNTER_START = new DateTimeImmutable('May 2, 2022 00:00:00 America/New_York');
|
||||
const DONATION_DRIVE_COUNTER_END = new DateTimeImmutable('May 8, 2022 23:59:00 America/New_York');
|
||||
|
|
|
@ -446,9 +446,6 @@ class Library{
|
|||
private static function FillBulkDownloadObject(string $dir, string $downloadType, string $urlRoot): stdClass{
|
||||
$obj = new stdClass();
|
||||
|
||||
/** @throws void */
|
||||
$now = new DateTimeImmutable();
|
||||
|
||||
// The count of ebooks in each file is stored as a filesystem attribute
|
||||
$obj->EbookCount = exec('attr -g se-ebook-count ' . escapeshellarg($dir)) ?: null;
|
||||
if($obj->EbookCount == null){
|
||||
|
@ -499,7 +496,7 @@ class Library{
|
|||
$obj->UpdatedString = $obj->Updated->format('M j');
|
||||
// Add a period to the abbreviated month, but not if it's May (the only 3-letter month)
|
||||
$obj->UpdatedString = preg_replace('/^(.+?)(?<!May) /', '\1. ', $obj->UpdatedString);
|
||||
if($obj->Updated->format('Y') != $now->format('Y')){
|
||||
if($obj->Updated->format('Y') != NOW->format('Y')){
|
||||
$obj->UpdatedString = $obj->Updated->format('M j, Y');
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,7 @@ class Log{
|
|||
return;
|
||||
}
|
||||
|
||||
/** @throws void */
|
||||
$now = new DateTimeImmutable();
|
||||
|
||||
fwrite($fp, $now->format('Y-m-d H:i:s') . "\t" . $this->RequestId . "\t" . $text . "\n");
|
||||
fwrite($fp, NOW->format('Y-m-d H:i:s') . "\t" . $this->RequestId . "\t" . $text . "\n");
|
||||
fclose($fp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,7 @@ class NewsletterSubscription{
|
|||
|
||||
$this->UserId = $this->User->UserId;
|
||||
|
||||
/** @throws void */
|
||||
$this->Created = new DateTimeImmutable();
|
||||
$this->Created = NOW;
|
||||
|
||||
try{
|
||||
Db::Query('
|
||||
|
|
|
@ -50,8 +50,7 @@ class OpdsFeed extends AtomFeed{
|
|||
if($this->HasChanged($this->Path)){
|
||||
// Files don't match, save the file and update the parent navigation feed with the last updated timestamp
|
||||
|
||||
/** @throws void */
|
||||
$this->Updated = new DateTimeImmutable();
|
||||
$this->Updated = NOW;
|
||||
|
||||
if($this->Parent !== null){
|
||||
$this->Parent->SaveUpdated($this->Id, $this->Updated);
|
||||
|
|
|
@ -21,8 +21,7 @@ class Patron{
|
|||
// *******
|
||||
|
||||
public function Create(): void{
|
||||
/** @throws void */
|
||||
$this->Created = new DateTimeImmutable();
|
||||
$this->Created = NOW;
|
||||
Db::Query('
|
||||
INSERT into Patrons (Created, UserId, IsAnonymous, AlternateName, IsSubscribedToEmails)
|
||||
values(?,
|
||||
|
|
|
@ -88,8 +88,7 @@ class Poll{
|
|||
|
||||
public function IsActive(): bool{
|
||||
/** @throws void */
|
||||
$now = new DateTimeImmutable();
|
||||
if( ($this->Start !== null && $this->Start > $now) || ($this->End !== null && $this->End < $now)){
|
||||
if( ($this->Start !== null && $this->Start > NOW) || ($this->End !== null && $this->End < NOW)){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,7 @@ class RssFeed extends Feed{
|
|||
|
||||
protected function GetXmlString(): string{
|
||||
if($this->XmlString === null){
|
||||
/** @throws void */
|
||||
$timestamp = (new DateTimeImmutable())->format('r');
|
||||
$timestamp = NOW->format('r');
|
||||
$feed = Template::RssFeed(['url' => $this->Url, 'description' => $this->Description, 'title' => $this->Title, 'entries' => $this->Entries, 'updated' => $timestamp]);
|
||||
|
||||
$this->XmlString = $this->CleanXmlString($feed);
|
||||
|
|
|
@ -60,8 +60,7 @@ class Session{
|
|||
$uuid = Uuid::uuid4();
|
||||
$this->SessionId = $uuid->toString();
|
||||
|
||||
/** @throws void */
|
||||
$this->Created = new DateTimeImmutable();
|
||||
$this->Created = NOW;
|
||||
Db::Query('
|
||||
INSERT into Sessions (UserId, SessionId, Created)
|
||||
values (?,
|
||||
|
|
|
@ -85,8 +85,7 @@ class User{
|
|||
$uuid = Uuid::uuid4();
|
||||
$this->Uuid = $uuid->toString();
|
||||
|
||||
/** @throws void */
|
||||
$this->Created = new DateTimeImmutable();
|
||||
$this->Created = NOW;
|
||||
|
||||
$this->PasswordHash = null;
|
||||
if($password !== null){
|
||||
|
|
|
@ -114,15 +114,13 @@ usort($allEbooks, 'SortByUpdatedDesc');
|
|||
usort($newestEbooks, function($a, $b){ return $b->Created <=> $a->Created; });
|
||||
$newestEbooks = array_slice($newestEbooks, 0, $ebooksPerNewestEbooksFeed);
|
||||
|
||||
$now = new DateTimeImmutable();
|
||||
|
||||
// Create OPDS feeds.
|
||||
$opdsRootEntries = [
|
||||
new OpdsNavigationEntry(
|
||||
'Newest Standard Ebooks',
|
||||
'The ' . number_format($ebooksPerNewestEbooksFeed) . ' latest Standard Ebooks, most-recently-released first.',
|
||||
'/feeds/opds/new-releases',
|
||||
$now,
|
||||
NOW,
|
||||
'http://opds-spec.org/sort/new',
|
||||
'acquisition'
|
||||
),
|
||||
|
@ -130,51 +128,51 @@ $opdsRootEntries = [
|
|||
'Standard Ebooks by Subject',
|
||||
'Browse Standard Ebooks by subject.',
|
||||
'/feeds/opds/subjects',
|
||||
$now,
|
||||
NOW,
|
||||
'subsection',
|
||||
'navigation'),
|
||||
new OpdsNavigationEntry(
|
||||
'Standard Ebooks by Collection',
|
||||
'Browse Standard Ebooks by collection.',
|
||||
'/feeds/opds/collections',
|
||||
$now,
|
||||
NOW,
|
||||
'subsection',
|
||||
'navigation'),
|
||||
new OpdsNavigationEntry(
|
||||
'Standard Ebooks by Author',
|
||||
'Browse Standard Ebooks by author.',
|
||||
'/feeds/opds/authors',
|
||||
$now,
|
||||
NOW,
|
||||
'subsection',
|
||||
'navigation'),
|
||||
new OpdsNavigationEntry(
|
||||
'All Standard Ebooks',
|
||||
'All Standard Ebooks, most-recently-updated first. This is a Complete Acquisition Feed as defined in OPDS 1.2 §2.5.',
|
||||
'/feeds/opds/all',
|
||||
$now,
|
||||
NOW,
|
||||
'http://opds-spec.org/crawlable',
|
||||
'acquisition')
|
||||
];
|
||||
|
||||
$opdsRoot = new OpdsNavigationFeed('Standard Ebooks', 'The Standard Ebooks catalog.', '/feeds/opds', $webRoot . '/feeds/opds/index.xml', $opdsRootEntries, null);
|
||||
SaveFeed($opdsRoot, $force, null, null, $now);
|
||||
SaveFeed($opdsRoot, $force, null, null, NOW);
|
||||
|
||||
// Create the Subjects feeds.
|
||||
CreateOpdsCollectionFeed('subject', '/feeds/opds/subjects', 'Standard Ebooks in the “%s” subject, most-recently-released first.', $subjects, $ebooksBySubject, $now, $webRoot, $opdsRoot, $force);
|
||||
CreateOpdsCollectionFeed('subject', '/feeds/opds/subjects', 'Standard Ebooks in the “%s” subject, most-recently-released first.', $subjects, $ebooksBySubject, NOW, $webRoot, $opdsRoot, $force);
|
||||
|
||||
// Create the Collections feeds.
|
||||
CreateOpdsCollectionFeed('collection', '/feeds/opds/collections', 'Standard Ebooks in the “%s” collection, most-recently-released first.', $collections, $ebooksByCollection, $now, $webRoot, $opdsRoot, $force);
|
||||
CreateOpdsCollectionFeed('collection', '/feeds/opds/collections', 'Standard Ebooks in the “%s” collection, most-recently-released first.', $collections, $ebooksByCollection, NOW, $webRoot, $opdsRoot, $force);
|
||||
|
||||
// Create the Author feeds.
|
||||
CreateOpdsCollectionFeed('author', '/feeds/opds/authors', 'Standard Ebooks by %s, most-recently-released first.', $authors, $ebooksByAuthor, $now, $webRoot, $opdsRoot, $force);
|
||||
CreateOpdsCollectionFeed('author', '/feeds/opds/authors', 'Standard Ebooks by %s, most-recently-released first.', $authors, $ebooksByAuthor, NOW, $webRoot, $opdsRoot, $force);
|
||||
|
||||
// Create the All feed.
|
||||
$allFeed = new OpdsAcquisitionFeed('All Standard Ebooks', 'All Standard Ebooks, most-recently-updated first. This is a Complete Acquisition Feed as defined in OPDS 1.2 §2.5.', '/feeds/opds/all', $webRoot . '/feeds/opds/all.xml', $allEbooks, $opdsRoot, true);
|
||||
SaveFeed($allFeed, $force, null, null, $now);
|
||||
SaveFeed($allFeed, $force, null, null, NOW);
|
||||
|
||||
// Create the Newest feed.
|
||||
$newestFeed = new OpdsAcquisitionFeed('Newest Standard Ebooks', 'The ' . number_format($ebooksPerNewestEbooksFeed) . ' latest Standard Ebooks, most-recently-released first.', '/feeds/opds/new-releases', $webRoot . '/feeds/opds/new-releases.xml', $newestEbooks, $opdsRoot);
|
||||
SaveFeed($newestFeed, $force, null, null, $now);
|
||||
SaveFeed($newestFeed, $force, null, null, NOW);
|
||||
|
||||
|
||||
|
||||
|
@ -190,11 +188,11 @@ SaveFeed($newestRssFeed, $force, null, null);
|
|||
|
||||
// Create the Atom All feed.
|
||||
$allAtomFeed = new AtomFeed('Standard Ebooks - All Ebooks', 'All Standard Ebooks, most-recently-released first.', '/feeds/atom/all', $webRoot . '/feeds/atom/all.xml', $allEbooks);
|
||||
SaveFeed($allAtomFeed, $force, null, null, $now);
|
||||
SaveFeed($allAtomFeed, $force, null, null, NOW);
|
||||
|
||||
// Create the Atom Newest feed.
|
||||
$newestAtomFeed = new AtomFeed('Standard Ebooks - Newest Ebooks', 'The ' . number_format($ebooksPerNewestEbooksFeed) . ' latest Standard Ebooks, most-recently-released first.', '/feeds/atom/new-releases', $webRoot . '/feeds/atom/new-releases.xml', $newestEbooks);
|
||||
SaveFeed($newestAtomFeed, $force, null, null, $now);
|
||||
SaveFeed($newestAtomFeed, $force, null, null, NOW);
|
||||
|
||||
// Generate each individual subject feed.
|
||||
foreach($ebooksBySubject as $subject => $ebooks){
|
||||
|
@ -207,7 +205,7 @@ foreach($ebooksBySubject as $subject => $ebooks){
|
|||
SaveFeed($subjectRssFeed, $force, $subjects[$subject]['name'], $subjects[$subject]['sortedname']);
|
||||
|
||||
$subjectAtomFeed = new AtomFeed($title, $subtitle, '/feeds/atom/subjects/' . Formatter::MakeUrlSafe($subject), $webRoot . '/feeds/atom/subjects/' . Formatter::MakeUrlSafe($subject) . '.xml', $ebooks);
|
||||
SaveFeed($subjectAtomFeed, $force, $subjects[$subject]['name'], $subjects[$subject]['sortedname'], $now);
|
||||
SaveFeed($subjectAtomFeed, $force, $subjects[$subject]['name'], $subjects[$subject]['sortedname'], NOW);
|
||||
}
|
||||
|
||||
// Generate each individual collection feed.
|
||||
|
@ -223,7 +221,7 @@ foreach($ebooksByCollection as $collection => $ebooks){
|
|||
SaveFeed($collectionRssFeed, $force, $collections[$collection]['name'], $collections[$collection]['sortedname']);
|
||||
|
||||
$collectionAtomFeed = new AtomFeed($title, $subtitle, '/feeds/atom/collections/' . Formatter::MakeUrlSafe($collection), $webRoot . '/feeds/atom/collections/' . Formatter::MakeUrlSafe($collection) . '.xml', $ebooks);
|
||||
SaveFeed($collectionAtomFeed, $force, $collections[$collection]['name'], $collections[$collection]['sortedname'], $now);
|
||||
SaveFeed($collectionAtomFeed, $force, $collections[$collection]['name'], $collections[$collection]['sortedname'], NOW);
|
||||
}
|
||||
|
||||
// Generate each individual author feed.
|
||||
|
@ -237,7 +235,7 @@ foreach($ebooksByAuthor as $collection => $ebooks){
|
|||
SaveFeed($collectionRssFeed, $force, $authors[$collection]['name'], $authors[$collection]['sortedname']);
|
||||
|
||||
$collectionAtomFeed = new AtomFeed($title, $subtitle, '/feeds/atom/authors/' . $authors[$collection]['id'], $webRoot . '/feeds/atom/authors/' . $authors[$collection]['id'] . '.xml', $ebooks);
|
||||
SaveFeed($collectionAtomFeed, $force, $authors[$collection]['name'], $authors[$collection]['sortedname'], $now);
|
||||
SaveFeed($collectionAtomFeed, $force, $authors[$collection]['name'], $authors[$collection]['sortedname'], NOW);
|
||||
}
|
||||
|
||||
// Set ownership and permissions.
|
||||
|
|
|
@ -46,8 +46,7 @@ $lastSeenTransactionId = null;
|
|||
$firstTransactionId = null;
|
||||
$transactionFilePath = '/tmp/last-fa-donation';
|
||||
$transactionIds = [];
|
||||
$now = new DateTimeImmutable();
|
||||
$today = $now->format('n/j/Y');
|
||||
$today = NOW->format('n/j/Y');
|
||||
$faItemsPerPage = 20; // How many items are on a full page of FA results?
|
||||
|
||||
// General plan: Read /tmp/last-fa-donation to see what the last transaction ID was that we processed.
|
||||
|
@ -94,7 +93,7 @@ try{
|
|||
}
|
||||
|
||||
if($lastSeenTransactionId === null){
|
||||
$log->Write('No last transaction ID, checking everything from ' . $now->format('Y-m-d'));
|
||||
$log->Write('No last transaction ID, checking everything from ' . NOW->format('Y-m-d'));
|
||||
}
|
||||
else{
|
||||
$log->Write('Checking from last transaction ID ' . $lastSeenTransactionId);
|
||||
|
|
|
@ -11,7 +11,6 @@ use function Safe\shell_exec;
|
|||
// Get a list of payments that are within 1 year / 45 days of today, and deactivate Patrons Circle members who aren't in that list.
|
||||
// We give a 15 day grace period to Patrons Circle members because sometimes FA can be delayed in charging.
|
||||
|
||||
$now = new DateTimeImmutable();
|
||||
$lastYear = new DateTimeImmutable('-1 year');
|
||||
|
||||
$expiredPatrons = Db::Query('
|
||||
|
@ -29,7 +28,7 @@ $expiredPatrons = Db::Query('
|
|||
(IsRecurring = false and Amount >= 100 and Created > ? - interval 1 year)
|
||||
)
|
||||
)
|
||||
', [$now, $now], Patron::class);
|
||||
', [NOW, NOW], Patron::class);
|
||||
|
||||
if(sizeof($expiredPatrons) > 0){
|
||||
$ebooksThisYear = 0;
|
||||
|
@ -54,7 +53,7 @@ if(sizeof($expiredPatrons) > 0){
|
|||
UPDATE Patrons
|
||||
set Ended = ?
|
||||
where UserId = ?
|
||||
', [$now, $patron->UserId]);
|
||||
', [NOW, $patron->UserId]);
|
||||
|
||||
Db::Query('
|
||||
UPDATE Benefits
|
||||
|
|
|
@ -9,8 +9,6 @@ if($artwork === null){
|
|||
}
|
||||
|
||||
$isEditForm = $isEditForm ?? false;
|
||||
|
||||
$now = new DateTimeImmutable('now', new DateTimeZone('America/Juneau')); // Latest continental US time zone
|
||||
?>
|
||||
<fieldset>
|
||||
<legend>Artist details</legend>
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<? if($GLOBALS['User'] === null){
|
||||
|
||||
// The Kindle browsers renders <aside> as an undismissable popup. Serve a <div> to Kindle instead. See https://github.com/standardebooks/web/issues/204
|
||||
$element = 'aside';
|
||||
|
||||
|
@ -7,10 +6,8 @@
|
|||
$element = 'div';
|
||||
}
|
||||
?>
|
||||
|
||||
<<?= $element ?> class="donation">
|
||||
<p>We rely on your support to help us keep producing beautiful, free, and unrestricted editions of literature for the digital age.</p>
|
||||
<p>Will you <a href="/donate">support our efforts with a donation</a>?</p>
|
||||
</<?= $element ?>>
|
||||
|
||||
<<?= $element ?> class="donation">
|
||||
<p>We rely on your support to help us keep producing beautiful, free, and unrestricted editions of literature for the digital age.</p>
|
||||
<p>Will you <a href="/donate">support our efforts with a donation</a>?</p>
|
||||
</<?= $element ?>>
|
||||
<? } ?>
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
<?
|
||||
use Safe\DateTimeImmutable;
|
||||
|
||||
$start = new DateTimeImmutable(DONATION_DRIVE_COUNTER_START);
|
||||
$end = new DateTimeImmutable(DONATION_DRIVE_COUNTER_END);
|
||||
$now = new DateTimeImmutable();
|
||||
|
||||
// Hide the alert if the user has closed it
|
||||
if(!DONATION_DRIVE_COUNTER_ON || ($autoHide ?? $_COOKIE['hide-donation-alert'] ?? false) || $now > $end){
|
||||
// Hide the alert if the user has closed it.
|
||||
if(!DONATION_DRIVE_COUNTER_ON || ($autoHide ?? $_COOKIE['hide-donation-alert'] ?? false) || NOW > DONATION_DRIVE_COUNTER_END){
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -14,12 +8,12 @@ $autoHide = $autoHide ?? true;
|
|||
$showDonateButton = $showDonateButton ?? true;
|
||||
$current = 0;
|
||||
|
||||
if($now < $start || $now > $end){
|
||||
if(NOW < DONATION_DRIVE_COUNTER_START || NOW > DONATION_DRIVE_COUNTER_END){
|
||||
return;
|
||||
}
|
||||
|
||||
$deadline = $end->format('F j');
|
||||
$timeLeft = $now->diff($end);
|
||||
$deadline = DONATION_DRIVE_COUNTER_END->format('F j');
|
||||
$timeLeft = NOW->diff(DONATION_DRIVE_COUNTER_END);
|
||||
$timeString = '';
|
||||
if($timeLeft->d < 1 && $timeLeft->h < 20){
|
||||
$timeString = 'Just hours';
|
||||
|
@ -44,14 +38,13 @@ else{
|
|||
}
|
||||
|
||||
$digits = str_split(str_pad($current, 3, "0", STR_PAD_LEFT))
|
||||
|
||||
?>
|
||||
<aside class="donation counter closable">
|
||||
<? if($autoHide){ ?>
|
||||
<form action="/settings" method="post">
|
||||
<input type="hidden" name="hide-donation-alert" value="1" />
|
||||
<button class="close" title="Close this box">Close this box</button>
|
||||
</form>
|
||||
<form action="/settings" method="post">
|
||||
<input type="hidden" name="hide-donation-alert" value="true" />
|
||||
<button class="close" title="Close this box">Close this box</button>
|
||||
</form>
|
||||
<? } ?>
|
||||
<header>
|
||||
<p><?= $timeString ?> left to help us win $1,000</p>
|
||||
|
@ -64,5 +57,9 @@ $digits = str_split(str_pad($current, 3, "0", STR_PAD_LEFT))
|
|||
<p><strong>Each one-time donation of any amount to Standard Ebooks through <?= $deadline ?> gives us one entry in this $1,000 giveaway.</strong> The more donations we receive through <?= $deadline ?>, the more chances we have to win!</p>
|
||||
<p><strong>This is a great time to <a href="/donate#patrons-circle">join our Patrons Circle</a> with a one-time donation of $100.</strong> Not only will your donation support us directly, but it’ll give us one more entry in this big giveaway.</p>
|
||||
<p>Will you show your support for free, beautiful digital literature?</p>
|
||||
<? if($showDonateButton){ ?><p class="donate-button"><a class="button" href="/donate">Make a one-time donation!</a></p><? } ?>
|
||||
<? if($showDonateButton){ ?>
|
||||
<p class="donate-button">
|
||||
<a class="button" href="/donate">Make a one-time donation!</a>
|
||||
</p>
|
||||
<? } ?>
|
||||
</aside>
|
||||
|
|
|
@ -1,11 +1,6 @@
|
|||
<?
|
||||
use Safe\DateTimeImmutable;
|
||||
|
||||
$start = new DateTimeImmutable(DONATION_DRIVE_START);
|
||||
$end = new DateTimeImmutable(DONATION_DRIVE_END);
|
||||
$now = new DateTimeImmutable();
|
||||
$totalCurrent = 0;
|
||||
$baseTarget = 25;
|
||||
$baseTarget = 50;
|
||||
$stretchCurrent = 0;
|
||||
$stretchTarget = 20;
|
||||
|
||||
|
@ -17,9 +12,9 @@ if(
|
|||
||
|
||||
$GLOBALS['User'] !== null // If a user is logged in
|
||||
||
|
||||
$start > $now // If the drive hasn't started yet
|
||||
DONATION_DRIVE_START > NOW // If the drive hasn't started yet
|
||||
||
|
||||
$now > $end // If the drive has ended
|
||||
NOW > DONATION_DRIVE_END // If the drive has ended
|
||||
){
|
||||
return;
|
||||
}
|
||||
|
@ -49,11 +44,11 @@ $totalCurrent = Db::QueryInt('
|
|||
where Created >= ?
|
||||
)
|
||||
) x
|
||||
', [$start, $start, $start]);
|
||||
', [DONATION_DRIVE_START, DONATION_DRIVE_START, DONATION_DRIVE_START]);
|
||||
|
||||
$totalTarget = $baseTarget;
|
||||
$deadline = $end->format('F j');
|
||||
$timeLeft = $now->diff($end);
|
||||
$deadline = DONATION_DRIVE_END->format('F j');
|
||||
$timeLeft = NOW->diff(DONATION_DRIVE_END);
|
||||
$timeString = '';
|
||||
if($timeLeft->days < 1 && $timeLeft->h < 20){
|
||||
$timeString = 'Just hours';
|
||||
|
@ -83,27 +78,26 @@ if($stretchTarget > 0 && $totalCurrent >= $baseTarget){
|
|||
$stretchCurrent = $totalCurrent - $baseTarget;
|
||||
$totalTarget = $baseTarget + $stretchTarget;
|
||||
}
|
||||
|
||||
?>
|
||||
<aside class="donation closable">
|
||||
<? if($autoHide){ ?>
|
||||
<form action="/settings" method="post">
|
||||
<input type="hidden" name="hide-donation-alert" value="1" />
|
||||
<button class="close" title="Close this box">Close this box</button>
|
||||
</form>
|
||||
<form action="/settings" method="post">
|
||||
<input type="hidden" name="hide-donation-alert" value="true" />
|
||||
<button class="close" title="Close this box">Close this box</button>
|
||||
</form>
|
||||
<? } ?>
|
||||
<? if(!$stretchOn){ ?>
|
||||
<header>
|
||||
<? if($timeLeft->days > 5){ ?>
|
||||
<p>Help us reach <?= number_format($baseTarget) ?> new patrons by <?= $deadline ?></p>
|
||||
<? }else{ ?>
|
||||
<p><?= $timeString ?> left to help us reach <?= number_format($baseTarget) ?> new patrons!</p>
|
||||
<? } ?>
|
||||
</header>
|
||||
<header>
|
||||
<? if($timeLeft->days > 5){ ?>
|
||||
<p>Help us reach <?= number_format($baseTarget) ?> new patrons by <?= $deadline ?></p>
|
||||
<? }else{ ?>
|
||||
<p><?= $timeString ?> left to help us reach <?= number_format($baseTarget) ?> new patrons!</p>
|
||||
<? } ?>
|
||||
</header>
|
||||
<? }else{ ?>
|
||||
<header>
|
||||
<p>Help us meet our stretch goal of<br/> <?= number_format($totalTarget) ?> new patrons by <?= $deadline ?></p>
|
||||
</header>
|
||||
<header>
|
||||
<p>Help us meet our stretch goal of<br/> <?= number_format($totalTarget) ?> new patrons by <?= $deadline ?></p>
|
||||
</header>
|
||||
<? } ?>
|
||||
<div class="progress">
|
||||
<div aria-hidden="true">
|
||||
|
@ -115,14 +109,20 @@ if($stretchTarget > 0 && $totalCurrent >= $baseTarget){
|
|||
<p class="target"><?= number_format($totalTarget) ?></p>
|
||||
</div>
|
||||
<progress max="<?= $baseTarget ?>" value="<?= $totalCurrent - $stretchCurrent ?>"></progress>
|
||||
<? if($stretchOn){ ?><progress class="stretch" max="<?= $stretchTarget ?>" value="<?= $stretchCurrent ?>"></progress><? } ?>
|
||||
<? if($stretchOn){ ?>
|
||||
<progress class="stretch" max="<?= $stretchTarget ?>" value="<?= $stretchCurrent ?>"></progress>
|
||||
<? } ?>
|
||||
</div>
|
||||
<? if($stretchOn){ ?>
|
||||
<p>When we started this drive, we set a goal of <?= number_format($baseTarget) ?> Patrons Circle members by <?= $deadline ?>. Thanks to the incredible generosity of literature lovers like you, we hit that goal!</p>
|
||||
<p>Since there’s still some time left in our drive, we thought we’d challenge our readers to help us reach our stretch goal of <?= number_format($totalTarget) ?> patrons, so that we can continue on a rock-solid financial footing. Will you help us with a donation, and support free and unrestricted digital literature?</p>
|
||||
<p>When we started this drive, we set a goal of <?= number_format($baseTarget) ?> Patrons Circle members by <?= $deadline ?>. Thanks to the incredible generosity of literature lovers like you, we hit that goal!</p>
|
||||
<p>Since there’s still some time left in our drive, we thought we’d challenge our readers to help us reach our stretch goal of <?= number_format($totalTarget) ?> patrons, so that we can continue on a rock-solid financial footing. Will you help us with a donation, and support free and unrestricted digital literature?</p>
|
||||
<? }else{ ?>
|
||||
<p>It takes a huge amount of resources and highly-skilled work to create and distribute each of our free ebooks, and we need your support to keep it up. That’s why we want to welcome <?= number_format($baseTarget) ?> new patrons by <?= $deadline ?>. It’s our patrons who keep us on the stable financial footing we need to continue producing and giving away beautiful ebooks.</p>
|
||||
<p>Will you become a patron, and support free and unrestricted digital literature?</p>
|
||||
<p>It takes a huge amount of resources and highly-skilled work to create and distribute each of our free ebooks, and we need your support to keep it up. That’s why we want to welcome <?= number_format($baseTarget) ?> new patrons by <?= $deadline ?>. It’s our patrons who keep us on the stable financial footing we need to continue producing and giving away beautiful ebooks.</p>
|
||||
<p>Will you become a patron, and support free and unrestricted digital literature?</p>
|
||||
<? } ?>
|
||||
<? if($showDonateButton){ ?>
|
||||
<p class="donate-button">
|
||||
<a class="button" href="/donate#patrons-circle">Join the patrons circle</a>
|
||||
</p>
|
||||
<? } ?>
|
||||
<? if($showDonateButton){ ?><p class="donate-button"><a class="button" href="/donate#patrons-circle">Join the patrons circle</a></p><? } ?>
|
||||
</aside>
|
||||
|
|
|
@ -40,7 +40,7 @@ catch(Exceptions\CollectionNotFoundException){
|
|||
<?= Template::DonationCounter() ?>
|
||||
<?= Template::DonationProgress() ?>
|
||||
<? if(!DONATION_DRIVE_ON && !DONATION_DRIVE_COUNTER_ON && DONATION_HOLIDAY_ALERT_ON){ ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<? } ?>
|
||||
<p class="ebooks-toolbar">
|
||||
<a class="button" href="/collections/<?= Formatter::EscapeHtml($collection) ?>/downloads">Download collection</a>
|
||||
|
|
|
@ -170,7 +170,7 @@ catch(Exceptions\EbookNotFoundException){
|
|||
<?= Template::DonationCounter() ?>
|
||||
<?= Template::DonationProgress() ?>
|
||||
<? if(!DONATION_DRIVE_ON && !DONATION_DRIVE_COUNTER_ON && DONATION_ALERT_ON){ ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<? } ?>
|
||||
<? if($ebook->LongDescription === null){ ?>
|
||||
<p><i>There’s no description for this ebook yet.</i></p>
|
||||
|
|
|
@ -110,7 +110,7 @@ catch(Exceptions\AppException $ex){
|
|||
<?= Template::DonationCounter() ?>
|
||||
<?= Template::DonationProgress() ?>
|
||||
<? if(!DONATION_DRIVE_ON && !DONATION_DRIVE_COUNTER_ON && DONATION_HOLIDAY_ALERT_ON){ ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<?= Template::DonationAlert() ?>
|
||||
<? } ?>
|
||||
<?= Template::SearchForm(['query' => $query, 'tags' => $tags, 'sort' => $sort, 'view' => $view, 'perPage' => $perPage]) ?>
|
||||
<? if(sizeof($ebooks) == 0){ ?>
|
||||
|
|
|
@ -25,7 +25,7 @@ print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . S
|
|||
<title>Search Results</title>
|
||||
<subtitle>Results for “<?= Formatter::EscapeXml($query) ?>”.</subtitle>
|
||||
<icon><?= SITE_URL ?>/images/logo.png</icon>
|
||||
<updated><?= (new DateTimeImmutable())->Format('Y-m-d\TH:i:s\Z') ?></updated>
|
||||
<updated><?= NOW->format('Y-m-d\TH:i:s\Z') ?></updated>
|
||||
<author>
|
||||
<name>Standard Ebooks</name>
|
||||
<uri><?= SITE_URL ?></uri>
|
||||
|
|
|
@ -26,7 +26,7 @@ print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"". SI
|
|||
<title>Search Results</title>
|
||||
<subtitle>Results for “<?= Formatter::EscapeXml($query) ?>”.</subtitle>
|
||||
<icon><?= SITE_URL ?>/images/logo.png</icon>
|
||||
<updated><?= (new DateTimeImmutable())->Format('Y-m-d\TH:i:s\Z') ?></updated>
|
||||
<updated><?= NOW->format('Y-m-d\TH:i:s\Z') ?></updated>
|
||||
<author>
|
||||
<name>Standard Ebooks</name>
|
||||
<uri><?= SITE_URL ?></uri>
|
||||
|
|
|
@ -24,7 +24,7 @@ print("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<?xml-stylesheet href=\"" . S
|
|||
<description>Results for “<?= Formatter::EscapeXml($query) ?>”.</description>
|
||||
<language>en-US</language>
|
||||
<copyright>https://creativecommons.org/publicdomain/zero/1.0/</copyright>
|
||||
<lastBuildDate><?= (new DateTimeImmutable())->format('r') ?></lastBuildDate>
|
||||
<lastBuildDate><?= NOW->format('r') ?></lastBuildDate>
|
||||
<docs>http://blogs.law.harvard.edu/tech/rss</docs>
|
||||
<atom:link href="<?= SITE_URL ?>/feeds/rss/all?query=<?= urlencode($query) ?>" rel="self" type="application/rss+xml"/>
|
||||
<atom:link href="<?= SITE_URL ?>/ebooks/opensearch" rel="search" type="application/opensearchdescription+xml" />
|
||||
|
|
|
@ -7,7 +7,7 @@ $canVote = true; // Allow non-logged-in users to see the 'vote' button
|
|||
try{
|
||||
$poll = Poll::GetByUrlName(HttpInput::Str(GET, 'pollurlname'));
|
||||
|
||||
if(!$poll->IsActive() && $poll->End !== null && $poll->End < new DateTimeImmutable()){
|
||||
if(!$poll->IsActive() && $poll->End !== null && $poll->End < NOW){
|
||||
// If the poll ended, redirect to the results
|
||||
header('Location: ' . $poll->Url . '/votes');
|
||||
exit();
|
||||
|
@ -47,7 +47,7 @@ catch(Exceptions\AppException){
|
|||
<a href="<?= $poll->Url ?>/votes" class="button">View results</a>
|
||||
</p>
|
||||
<? }else{ ?>
|
||||
<? if($poll->Start !== null && $poll->Start > new DateTimeImmutable()){ ?>
|
||||
<? if($poll->Start !== null && $poll->Start > NOW){ ?>
|
||||
<p class="center-notice">This poll opens on <?= $poll->Start->format('F j, Y g:i a') ?>.</p>
|
||||
<? }else{ ?>
|
||||
<p class="center-notice">This poll closed on <?= $poll->End->format('F j, Y g:i a') ?>.</p>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue