Changeset 3718060
- Timestamp:
- 09/29/2026 12:22:15 AM (4 weeks ago)
- Location:
- logicanvas-auctions
- Files:
-
- 509 added
- 1 deleted
- 46 edited
-
tags/1.2.0-development (deleted)
-
tags/1.2.1 (added)
-
tags/1.2.1-development (added)
-
tags/1.2.1-development/LICENSE (added)
-
tags/1.2.1-development/README.md (added)
-
tags/1.2.1-development/assets (added)
-
tags/1.2.1-development/assets/dist (added)
-
tags/1.2.1-development/assets/dist/css (added)
-
tags/1.2.1-development/assets/dist/css/admin.css (added)
-
tags/1.2.1-development/assets/dist/css/frontend.css (added)
-
tags/1.2.1-development/assets/dist/js (added)
-
tags/1.2.1-development/assets/dist/js/admin-actions.js (added)
-
tags/1.2.1-development/assets/dist/js/frontend.js (added)
-
tags/1.2.1-development/assets/dist/js/qrcode.min.js (added)
-
tags/1.2.1-development/assets/img (added)
-
tags/1.2.1-development/assets/img/logicanvas-auctions-logo.png (added)
-
tags/1.2.1-development/changelog.txt (added)
-
tags/1.2.1-development/composer.json (added)
-
tags/1.2.1-development/docs (added)
-
tags/1.2.1-development/docs/faq-and-guides.json (added)
-
tags/1.2.1-development/languages (added)
-
tags/1.2.1-development/languages/index.php (added)
-
tags/1.2.1-development/logicanvas-auctions.php (added)
-
tags/1.2.1-development/readme.txt (added)
-
tags/1.2.1-development/src (added)
-
tags/1.2.1-development/src/Admin (added)
-
tags/1.2.1-development/src/Admin/ActionUI.php (added)
-
tags/1.2.1-development/src/Admin/AuctionEditor.php (added)
-
tags/1.2.1-development/src/Admin/ListTables (added)
-
tags/1.2.1-development/src/Admin/Menu.php (added)
-
tags/1.2.1-development/src/Admin/Notices.php (added)
-
tags/1.2.1-development/src/Admin/Pages (added)
-
tags/1.2.1-development/src/Admin/Pages/AuctionsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/AwardsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/BidsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/DashboardPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/DiagnosticsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/HoldersPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/SettingsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/SettlementsPage.php (added)
-
tags/1.2.1-development/src/Admin/Pages/SetupWizard.php (added)
-
tags/1.2.1-development/src/Admin/PermalinkSettings.php (added)
-
tags/1.2.1-development/src/Admin/ReviewPrompt.php (added)
-
tags/1.2.1-development/src/Admin/Screen.php (added)
-
tags/1.2.1-development/src/Admin/Settings.php (added)
-
tags/1.2.1-development/src/Admin/Views (added)
-
tags/1.2.1-development/src/Application (added)
-
tags/1.2.1-development/src/Application/AuctionPresenter.php (added)
-
tags/1.2.1-development/src/Autoloader.php (added)
-
tags/1.2.1-development/src/CLI (added)
-
tags/1.2.1-development/src/CLI/Commands.php (added)
-
tags/1.2.1-development/src/Config.php (added)
-
tags/1.2.1-development/src/Container.php (added)
-
tags/1.2.1-development/src/Core (added)
-
tags/1.2.1-development/src/Core/Activator.php (added)
-
tags/1.2.1-development/src/Core/Capabilities.php (added)
-
tags/1.2.1-development/src/Core/ClockInterface.php (added)
-
tags/1.2.1-development/src/Core/Deactivator.php (added)
-
tags/1.2.1-development/src/Core/Dependencies.php (added)
-
tags/1.2.1-development/src/Core/FrozenClock.php (added)
-
tags/1.2.1-development/src/Core/Hooks.php (added)
-
tags/1.2.1-development/src/Core/Installer.php (added)
-
tags/1.2.1-development/src/Core/Logger.php (added)
-
tags/1.2.1-development/src/Core/PostTypes.php (added)
-
tags/1.2.1-development/src/Core/SystemClock.php (added)
-
tags/1.2.1-development/src/Domain (added)
-
tags/1.2.1-development/src/Domain/Auction (added)
-
tags/1.2.1-development/src/Domain/Auction/Auction.php (added)
-
tags/1.2.1-development/src/Domain/Auction/AuctionInputSanitizer.php (added)
-
tags/1.2.1-development/src/Domain/Auction/AuctionRepositoryInterface.php (added)
-
tags/1.2.1-development/src/Domain/Auction/AuctionService.php (added)
-
tags/1.2.1-development/src/Domain/Auction/AuctionState.php (added)
-
tags/1.2.1-development/src/Domain/Auction/AuctionType.php (added)
-
tags/1.2.1-development/src/Domain/Auction/DemoAuction.php (added)
-
tags/1.2.1-development/src/Domain/Auction/InvalidTransitionException.php (added)
-
tags/1.2.1-development/src/Domain/Auction/LiveAuctionService.php (added)
-
tags/1.2.1-development/src/Domain/Auction/LiveStateMachine.php (added)
-
tags/1.2.1-development/src/Domain/Auction/TimedStateMachine.php (added)
-
tags/1.2.1-development/src/Domain/Auction/Visibility.php (added)
-
tags/1.2.1-development/src/Domain/Award (added)
-
tags/1.2.1-development/src/Domain/Award/AwardService.php (added)
-
tags/1.2.1-development/src/Domain/Bidding (added)
-
tags/1.2.1-development/src/Domain/Bidding/Bid.php (added)
-
tags/1.2.1-development/src/Domain/Bidding/BidRejectedException.php (added)
-
tags/1.2.1-development/src/Domain/Bidding/BidRepositoryInterface.php (added)
-
tags/1.2.1-development/src/Domain/Bidding/BidService.php (added)
-
tags/1.2.1-development/src/Domain/Bidding/IncrementCalculator.php (added)
-
tags/1.2.1-development/src/Domain/Bidding/ProxyBidding.php (added)
-
tags/1.2.1-development/src/Domain/Holder (added)
-
tags/1.2.1-development/src/Domain/Holder/HolderService.php (added)
-
tags/1.2.1-development/src/Domain/Invitation (added)
-
tags/1.2.1-development/src/Domain/Invitation/AccessService.php (added)
-
tags/1.2.1-development/src/Domain/Money (added)
-
tags/1.2.1-development/src/Domain/Money/Decimal.php (added)
-
tags/1.2.1-development/src/Domain/Money/Money.php (added)
-
tags/1.2.1-development/src/Domain/Order (added)
-
tags/1.2.1-development/src/Domain/Order/HolderOrderService.php (added)
-
tags/1.2.1-development/src/Domain/Order/OrderManagement.php (added)
-
tags/1.2.1-development/src/Domain/Settlement (added)
-
tags/1.2.1-development/src/Domain/Settlement/ManualPayoutProvider.php (added)
-
tags/1.2.1-development/src/Domain/Settlement/PayoutProviderInterface.php (added)
-
tags/1.2.1-development/src/Domain/Settlement/PayoutRequestService.php (added)
-
tags/1.2.1-development/src/Domain/Settlement/SettlementService.php (added)
-
tags/1.2.1-development/src/Domain/Watch (added)
-
tags/1.2.1-development/src/Elementor (added)
-
tags/1.2.1-development/src/Elementor/Category.php (added)
-
tags/1.2.1-development/src/Elementor/Compatibility.php (added)
-
tags/1.2.1-development/src/Elementor/DynamicTags (added)
-
tags/1.2.1-development/src/Elementor/DynamicTags/AuctionTag.php (added)
-
tags/1.2.1-development/src/Elementor/Loader.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionDetailsWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionGalleryWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionGridWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionSearchWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionShareWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/AuctionStatusWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/BidHistoryWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/BidPanelWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/BidderDashboardWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/CountdownWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/CurrentPriceWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/HolderDashboardWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/LiveHostWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/LiveRoomWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/LoginWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/MyAuctionsWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/MyBidsWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/MyWinsWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/ShortcodeWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/SingleAuctionWidget.php (added)
-
tags/1.2.1-development/src/Elementor/Widgets/SubmissionFormWidget.php (added)
-
tags/1.2.1-development/src/Frontend (added)
-
tags/1.2.1-development/src/Frontend/AccessGuard.php (added)
-
tags/1.2.1-development/src/Frontend/Assets.php (added)
-
tags/1.2.1-development/src/Frontend/AuthPages.php (added)
-
tags/1.2.1-development/src/Frontend/Dashboards (added)
-
tags/1.2.1-development/src/Frontend/Dashboards/AccountPage.php (added)
-
tags/1.2.1-development/src/Frontend/Dashboards/AccountProfile.php (added)
-
tags/1.2.1-development/src/Frontend/Dashboards/AccountRouter.php (added)
-
tags/1.2.1-development/src/Frontend/Dashboards/BidderDashboard.php (added)
-
tags/1.2.1-development/src/Frontend/Dashboards/HolderDashboard.php (added)
-
tags/1.2.1-development/src/Frontend/Design.php (added)
-
tags/1.2.1-development/src/Frontend/PluginPages.php (added)
-
tags/1.2.1-development/src/Frontend/Shortcodes (added)
-
tags/1.2.1-development/src/Frontend/Shortcodes.php (added)
-
tags/1.2.1-development/src/Frontend/TemplateLoader.php (added)
-
tags/1.2.1-development/src/Frontend/WinnerPaymentRedirect.php (added)
-
tags/1.2.1-development/src/Infrastructure (added)
-
tags/1.2.1-development/src/Infrastructure/Database (added)
-
tags/1.2.1-development/src/Infrastructure/Database/Migrator.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/OptionLock.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/QueryCache.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/RateLimiter.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/Schema.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/Transaction.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/WpdbAuctionRepository.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/WpdbAuditRepository.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/WpdbBidRepository.php (added)
-
tags/1.2.1-development/src/Infrastructure/Database/WpdbEventRepository.php (added)
-
tags/1.2.1-development/src/Infrastructure/Media (added)
-
tags/1.2.1-development/src/Infrastructure/Media/ImageUploader.php (added)
-
tags/1.2.1-development/src/Infrastructure/Media/ProofUploader.php (added)
-
tags/1.2.1-development/src/Infrastructure/Realtime (added)
-
tags/1.2.1-development/src/Infrastructure/Realtime/PollingTransport.php (added)
-
tags/1.2.1-development/src/Infrastructure/Realtime/PushTransportInterface.php (added)
-
tags/1.2.1-development/src/Infrastructure/Realtime/RealtimeTransportInterface.php (added)
-
tags/1.2.1-development/src/Infrastructure/Scheduler (added)
-
tags/1.2.1-development/src/Infrastructure/Scheduler/AuctionScheduler.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/CatalogGuard.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/CheckoutLock.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/Compatibility.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/MyAccount.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/OrderObserver.php (added)
-
tags/1.2.1-development/src/Infrastructure/WooCommerce/ProductSync.php (added)
-
tags/1.2.1-development/src/Notifications (added)
-
tags/1.2.1-development/src/Notifications/Emails (added)
-
tags/1.2.1-development/src/Notifications/Emails/BidAcceptedEmail.php (added)
-
tags/1.2.1-development/src/Notifications/Emails/OutbidEmail.php (added)
-
tags/1.2.1-development/src/Notifications/Emails/WinnerEmail.php (added)
-
tags/1.2.1-development/src/Notifications/NotificationService.php (added)
-
tags/1.2.1-development/src/Plugin.php (added)
-
tags/1.2.1-development/src/Privacy (added)
-
tags/1.2.1-development/src/Privacy/PersonalData.php (added)
-
tags/1.2.1-development/src/REST (added)
-
tags/1.2.1-development/src/REST/AuctionController.php (added)
-
tags/1.2.1-development/src/REST/BidController.php (added)
-
tags/1.2.1-development/src/REST/CheckoutController.php (added)
-
tags/1.2.1-development/src/REST/EventController.php (added)
-
tags/1.2.1-development/src/REST/HolderController.php (added)
-
tags/1.2.1-development/src/REST/LiveController.php (added)
-
tags/1.2.1-development/src/REST/MeController.php (added)
-
tags/1.2.1-development/src/REST/MediaController.php (added)
-
tags/1.2.1-development/src/REST/OrderController.php (added)
-
tags/1.2.1-development/src/REST/PayoutController.php (added)
-
tags/1.2.1-development/src/REST/ProductController.php (added)
-
tags/1.2.1-development/src/REST/RestAccess.php (added)
-
tags/1.2.1-development/src/REST/RestController.php (added)
-
tags/1.2.1-development/src/REST/WatchController.php (added)
-
tags/1.2.1-development/src/Support (added)
-
tags/1.2.1-development/src/Support/AuctionCategory.php (added)
-
tags/1.2.1-development/src/Support/AuctionQr.php (added)
-
tags/1.2.1-development/src/Support/Diagnostics.php (added)
-
tags/1.2.1-development/src/Support/ListingContent.php (added)
-
tags/1.2.1-development/src/Support/SeoCompat.php (added)
-
tags/1.2.1-development/src/Support/ShareLinks.php (added)
-
tags/1.2.1-development/templates (added)
-
tags/1.2.1-development/templates/account (added)
-
tags/1.2.1-development/templates/account/address.php (added)
-
tags/1.2.1-development/templates/account/bids.php (added)
-
tags/1.2.1-development/templates/account/create.php (added)
-
tags/1.2.1-development/templates/account/edit.php (added)
-
tags/1.2.1-development/templates/account/listings.php (added)
-
tags/1.2.1-development/templates/account/orders.php (added)
-
tags/1.2.1-development/templates/account/overview.php (added)
-
tags/1.2.1-development/templates/account/payouts.php (added)
-
tags/1.2.1-development/templates/account/pickup.php (added)
-
tags/1.2.1-development/templates/account/purchases.php (added)
-
tags/1.2.1-development/templates/account/shell.php (added)
-
tags/1.2.1-development/templates/account/watchlist.php (added)
-
tags/1.2.1-development/templates/bidder (added)
-
tags/1.2.1-development/templates/bidder/dashboard.php (added)
-
tags/1.2.1-development/templates/bidder/my-bids.php (added)
-
tags/1.2.1-development/templates/bidder/my-wins.php (added)
-
tags/1.2.1-development/templates/emails (added)
-
tags/1.2.1-development/templates/emails/bid-accepted.php (added)
-
tags/1.2.1-development/templates/emails/outbid.php (added)
-
tags/1.2.1-development/templates/emails/plain (added)
-
tags/1.2.1-development/templates/emails/plain/bid-accepted.php (added)
-
tags/1.2.1-development/templates/emails/plain/outbid.php (added)
-
tags/1.2.1-development/templates/emails/plain/winner.php (added)
-
tags/1.2.1-development/templates/emails/winner.php (added)
-
tags/1.2.1-development/templates/frontend (added)
-
tags/1.2.1-development/templates/frontend/auth.php (added)
-
tags/1.2.1-development/templates/frontend/bid-history.php (added)
-
tags/1.2.1-development/templates/frontend/grid.php (added)
-
tags/1.2.1-development/templates/frontend/pay.php (added)
-
tags/1.2.1-development/templates/frontend/single.php (added)
-
tags/1.2.1-development/templates/holder (added)
-
tags/1.2.1-development/templates/holder/apply.php (added)
-
tags/1.2.1-development/templates/holder/dashboard.php (added)
-
tags/1.2.1-development/templates/holder/form-edit.php (added)
-
tags/1.2.1-development/templates/holder/form-submit.php (added)
-
tags/1.2.1-development/templates/holder/submit.php (added)
-
tags/1.2.1-development/templates/live (added)
-
tags/1.2.1-development/templates/live/host.php (added)
-
tags/1.2.1-development/templates/live/room.php (added)
-
tags/1.2.1-development/templates/partials (added)
-
tags/1.2.1-development/templates/partials/accept-ready.php (added)
-
tags/1.2.1-development/templates/partials/account-sidebar.php (added)
-
tags/1.2.1-development/templates/partials/auction-table.php (added)
-
tags/1.2.1-development/templates/partials/share-social.php (added)
-
tags/1.2.1-development/templates/single (added)
-
tags/1.2.1-development/templates/single/single-auction.php (added)
-
tags/1.2.1-development/uninstall.php (added)
-
tags/1.2.1/LICENSE (added)
-
tags/1.2.1/README.md (added)
-
tags/1.2.1/assets (added)
-
tags/1.2.1/assets/dist (added)
-
tags/1.2.1/assets/dist/css (added)
-
tags/1.2.1/assets/dist/css/admin.css (added)
-
tags/1.2.1/assets/dist/css/frontend.css (added)
-
tags/1.2.1/assets/dist/js (added)
-
tags/1.2.1/assets/dist/js/admin-actions.js (added)
-
tags/1.2.1/assets/dist/js/frontend.js (added)
-
tags/1.2.1/assets/dist/js/qrcode.min.js (added)
-
tags/1.2.1/assets/img (added)
-
tags/1.2.1/assets/img/logicanvas-auctions-logo.png (added)
-
tags/1.2.1/changelog.txt (added)
-
tags/1.2.1/composer.json (added)
-
tags/1.2.1/docs (added)
-
tags/1.2.1/docs/faq-and-guides.json (added)
-
tags/1.2.1/languages (added)
-
tags/1.2.1/languages/index.php (added)
-
tags/1.2.1/logicanvas-auctions.php (added)
-
tags/1.2.1/readme.txt (added)
-
tags/1.2.1/src (added)
-
tags/1.2.1/src/Admin (added)
-
tags/1.2.1/src/Admin/ActionUI.php (added)
-
tags/1.2.1/src/Admin/AuctionEditor.php (added)
-
tags/1.2.1/src/Admin/ListTables (added)
-
tags/1.2.1/src/Admin/Menu.php (added)
-
tags/1.2.1/src/Admin/Notices.php (added)
-
tags/1.2.1/src/Admin/Pages (added)
-
tags/1.2.1/src/Admin/Pages/AuctionsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/AwardsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/BidsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/DashboardPage.php (added)
-
tags/1.2.1/src/Admin/Pages/DiagnosticsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/HoldersPage.php (added)
-
tags/1.2.1/src/Admin/Pages/SettingsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/SettlementsPage.php (added)
-
tags/1.2.1/src/Admin/Pages/SetupWizard.php (added)
-
tags/1.2.1/src/Admin/PermalinkSettings.php (added)
-
tags/1.2.1/src/Admin/ReviewPrompt.php (added)
-
tags/1.2.1/src/Admin/Screen.php (added)
-
tags/1.2.1/src/Admin/Settings.php (added)
-
tags/1.2.1/src/Admin/Views (added)
-
tags/1.2.1/src/Application (added)
-
tags/1.2.1/src/Application/AuctionPresenter.php (added)
-
tags/1.2.1/src/Autoloader.php (added)
-
tags/1.2.1/src/CLI (added)
-
tags/1.2.1/src/CLI/Commands.php (added)
-
tags/1.2.1/src/Config.php (added)
-
tags/1.2.1/src/Container.php (added)
-
tags/1.2.1/src/Core (added)
-
tags/1.2.1/src/Core/Activator.php (added)
-
tags/1.2.1/src/Core/Capabilities.php (added)
-
tags/1.2.1/src/Core/ClockInterface.php (added)
-
tags/1.2.1/src/Core/Deactivator.php (added)
-
tags/1.2.1/src/Core/Dependencies.php (added)
-
tags/1.2.1/src/Core/FrozenClock.php (added)
-
tags/1.2.1/src/Core/Hooks.php (added)
-
tags/1.2.1/src/Core/Installer.php (added)
-
tags/1.2.1/src/Core/Logger.php (added)
-
tags/1.2.1/src/Core/PostTypes.php (added)
-
tags/1.2.1/src/Core/SystemClock.php (added)
-
tags/1.2.1/src/Domain (added)
-
tags/1.2.1/src/Domain/Auction (added)
-
tags/1.2.1/src/Domain/Auction/Auction.php (added)
-
tags/1.2.1/src/Domain/Auction/AuctionInputSanitizer.php (added)
-
tags/1.2.1/src/Domain/Auction/AuctionRepositoryInterface.php (added)
-
tags/1.2.1/src/Domain/Auction/AuctionService.php (added)
-
tags/1.2.1/src/Domain/Auction/AuctionState.php (added)
-
tags/1.2.1/src/Domain/Auction/AuctionType.php (added)
-
tags/1.2.1/src/Domain/Auction/DemoAuction.php (added)
-
tags/1.2.1/src/Domain/Auction/InvalidTransitionException.php (added)
-
tags/1.2.1/src/Domain/Auction/LiveAuctionService.php (added)
-
tags/1.2.1/src/Domain/Auction/LiveStateMachine.php (added)
-
tags/1.2.1/src/Domain/Auction/TimedStateMachine.php (added)
-
tags/1.2.1/src/Domain/Auction/Visibility.php (added)
-
tags/1.2.1/src/Domain/Award (added)
-
tags/1.2.1/src/Domain/Award/AwardService.php (added)
-
tags/1.2.1/src/Domain/Bidding (added)
-
tags/1.2.1/src/Domain/Bidding/Bid.php (added)
-
tags/1.2.1/src/Domain/Bidding/BidRejectedException.php (added)
-
tags/1.2.1/src/Domain/Bidding/BidRepositoryInterface.php (added)
-
tags/1.2.1/src/Domain/Bidding/BidService.php (added)
-
tags/1.2.1/src/Domain/Bidding/IncrementCalculator.php (added)
-
tags/1.2.1/src/Domain/Bidding/ProxyBidding.php (added)
-
tags/1.2.1/src/Domain/Holder (added)
-
tags/1.2.1/src/Domain/Holder/HolderService.php (added)
-
tags/1.2.1/src/Domain/Invitation (added)
-
tags/1.2.1/src/Domain/Invitation/AccessService.php (added)
-
tags/1.2.1/src/Domain/Money (added)
-
tags/1.2.1/src/Domain/Money/Decimal.php (added)
-
tags/1.2.1/src/Domain/Money/Money.php (added)
-
tags/1.2.1/src/Domain/Order (added)
-
tags/1.2.1/src/Domain/Order/HolderOrderService.php (added)
-
tags/1.2.1/src/Domain/Order/OrderManagement.php (added)
-
tags/1.2.1/src/Domain/Settlement (added)
-
tags/1.2.1/src/Domain/Settlement/ManualPayoutProvider.php (added)
-
tags/1.2.1/src/Domain/Settlement/PayoutProviderInterface.php (added)
-
tags/1.2.1/src/Domain/Settlement/PayoutRequestService.php (added)
-
tags/1.2.1/src/Domain/Settlement/SettlementService.php (added)
-
tags/1.2.1/src/Domain/Watch (added)
-
tags/1.2.1/src/Elementor (added)
-
tags/1.2.1/src/Elementor/Category.php (added)
-
tags/1.2.1/src/Elementor/Compatibility.php (added)
-
tags/1.2.1/src/Elementor/DynamicTags (added)
-
tags/1.2.1/src/Elementor/DynamicTags/AuctionTag.php (added)
-
tags/1.2.1/src/Elementor/Loader.php (added)
-
tags/1.2.1/src/Elementor/Widgets (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionDetailsWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionGalleryWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionGridWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionSearchWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionShareWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/AuctionStatusWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/BidHistoryWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/BidPanelWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/BidderDashboardWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/CountdownWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/CurrentPriceWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/HolderDashboardWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/LiveHostWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/LiveRoomWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/LoginWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/MyAuctionsWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/MyBidsWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/MyWinsWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/ShortcodeWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/SingleAuctionWidget.php (added)
-
tags/1.2.1/src/Elementor/Widgets/SubmissionFormWidget.php (added)
-
tags/1.2.1/src/Frontend (added)
-
tags/1.2.1/src/Frontend/AccessGuard.php (added)
-
tags/1.2.1/src/Frontend/Assets.php (added)
-
tags/1.2.1/src/Frontend/AuthPages.php (added)
-
tags/1.2.1/src/Frontend/Dashboards (added)
-
tags/1.2.1/src/Frontend/Dashboards/AccountPage.php (added)
-
tags/1.2.1/src/Frontend/Dashboards/AccountProfile.php (added)
-
tags/1.2.1/src/Frontend/Dashboards/AccountRouter.php (added)
-
tags/1.2.1/src/Frontend/Dashboards/BidderDashboard.php (added)
-
tags/1.2.1/src/Frontend/Dashboards/HolderDashboard.php (added)
-
tags/1.2.1/src/Frontend/Design.php (added)
-
tags/1.2.1/src/Frontend/PluginPages.php (added)
-
tags/1.2.1/src/Frontend/Shortcodes (added)
-
tags/1.2.1/src/Frontend/Shortcodes.php (added)
-
tags/1.2.1/src/Frontend/TemplateLoader.php (added)
-
tags/1.2.1/src/Frontend/WinnerPaymentRedirect.php (added)
-
tags/1.2.1/src/Infrastructure (added)
-
tags/1.2.1/src/Infrastructure/Database (added)
-
tags/1.2.1/src/Infrastructure/Database/Migrator.php (added)
-
tags/1.2.1/src/Infrastructure/Database/OptionLock.php (added)
-
tags/1.2.1/src/Infrastructure/Database/QueryCache.php (added)
-
tags/1.2.1/src/Infrastructure/Database/RateLimiter.php (added)
-
tags/1.2.1/src/Infrastructure/Database/Schema.php (added)
-
tags/1.2.1/src/Infrastructure/Database/Transaction.php (added)
-
tags/1.2.1/src/Infrastructure/Database/WpdbAuctionRepository.php (added)
-
tags/1.2.1/src/Infrastructure/Database/WpdbAuditRepository.php (added)
-
tags/1.2.1/src/Infrastructure/Database/WpdbBidRepository.php (added)
-
tags/1.2.1/src/Infrastructure/Database/WpdbEventRepository.php (added)
-
tags/1.2.1/src/Infrastructure/Media (added)
-
tags/1.2.1/src/Infrastructure/Media/ImageUploader.php (added)
-
tags/1.2.1/src/Infrastructure/Media/ProofUploader.php (added)
-
tags/1.2.1/src/Infrastructure/Realtime (added)
-
tags/1.2.1/src/Infrastructure/Realtime/PollingTransport.php (added)
-
tags/1.2.1/src/Infrastructure/Realtime/PushTransportInterface.php (added)
-
tags/1.2.1/src/Infrastructure/Realtime/RealtimeTransportInterface.php (added)
-
tags/1.2.1/src/Infrastructure/Scheduler (added)
-
tags/1.2.1/src/Infrastructure/Scheduler/AuctionScheduler.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/CatalogGuard.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/CheckoutLock.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/Compatibility.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/MyAccount.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/OrderObserver.php (added)
-
tags/1.2.1/src/Infrastructure/WooCommerce/ProductSync.php (added)
-
tags/1.2.1/src/Notifications (added)
-
tags/1.2.1/src/Notifications/Emails (added)
-
tags/1.2.1/src/Notifications/Emails/BidAcceptedEmail.php (added)
-
tags/1.2.1/src/Notifications/Emails/OutbidEmail.php (added)
-
tags/1.2.1/src/Notifications/Emails/WinnerEmail.php (added)
-
tags/1.2.1/src/Notifications/NotificationService.php (added)
-
tags/1.2.1/src/Plugin.php (added)
-
tags/1.2.1/src/Privacy (added)
-
tags/1.2.1/src/Privacy/PersonalData.php (added)
-
tags/1.2.1/src/REST (added)
-
tags/1.2.1/src/REST/AuctionController.php (added)
-
tags/1.2.1/src/REST/BidController.php (added)
-
tags/1.2.1/src/REST/CheckoutController.php (added)
-
tags/1.2.1/src/REST/EventController.php (added)
-
tags/1.2.1/src/REST/HolderController.php (added)
-
tags/1.2.1/src/REST/LiveController.php (added)
-
tags/1.2.1/src/REST/MeController.php (added)
-
tags/1.2.1/src/REST/MediaController.php (added)
-
tags/1.2.1/src/REST/OrderController.php (added)
-
tags/1.2.1/src/REST/PayoutController.php (added)
-
tags/1.2.1/src/REST/ProductController.php (added)
-
tags/1.2.1/src/REST/RestAccess.php (added)
-
tags/1.2.1/src/REST/RestController.php (added)
-
tags/1.2.1/src/REST/WatchController.php (added)
-
tags/1.2.1/src/Support (added)
-
tags/1.2.1/src/Support/AuctionCategory.php (added)
-
tags/1.2.1/src/Support/AuctionQr.php (added)
-
tags/1.2.1/src/Support/Diagnostics.php (added)
-
tags/1.2.1/src/Support/ListingContent.php (added)
-
tags/1.2.1/src/Support/SeoCompat.php (added)
-
tags/1.2.1/src/Support/ShareLinks.php (added)
-
tags/1.2.1/templates (added)
-
tags/1.2.1/templates/account (added)
-
tags/1.2.1/templates/account/address.php (added)
-
tags/1.2.1/templates/account/bids.php (added)
-
tags/1.2.1/templates/account/create.php (added)
-
tags/1.2.1/templates/account/edit.php (added)
-
tags/1.2.1/templates/account/listings.php (added)
-
tags/1.2.1/templates/account/orders.php (added)
-
tags/1.2.1/templates/account/overview.php (added)
-
tags/1.2.1/templates/account/payouts.php (added)
-
tags/1.2.1/templates/account/pickup.php (added)
-
tags/1.2.1/templates/account/purchases.php (added)
-
tags/1.2.1/templates/account/shell.php (added)
-
tags/1.2.1/templates/account/watchlist.php (added)
-
tags/1.2.1/templates/bidder (added)
-
tags/1.2.1/templates/bidder/dashboard.php (added)
-
tags/1.2.1/templates/bidder/my-bids.php (added)
-
tags/1.2.1/templates/bidder/my-wins.php (added)
-
tags/1.2.1/templates/emails (added)
-
tags/1.2.1/templates/emails/bid-accepted.php (added)
-
tags/1.2.1/templates/emails/outbid.php (added)
-
tags/1.2.1/templates/emails/plain (added)
-
tags/1.2.1/templates/emails/plain/bid-accepted.php (added)
-
tags/1.2.1/templates/emails/plain/outbid.php (added)
-
tags/1.2.1/templates/emails/plain/winner.php (added)
-
tags/1.2.1/templates/emails/winner.php (added)
-
tags/1.2.1/templates/frontend (added)
-
tags/1.2.1/templates/frontend/auth.php (added)
-
tags/1.2.1/templates/frontend/bid-history.php (added)
-
tags/1.2.1/templates/frontend/grid.php (added)
-
tags/1.2.1/templates/frontend/pay.php (added)
-
tags/1.2.1/templates/frontend/single.php (added)
-
tags/1.2.1/templates/holder (added)
-
tags/1.2.1/templates/holder/apply.php (added)
-
tags/1.2.1/templates/holder/dashboard.php (added)
-
tags/1.2.1/templates/holder/form-edit.php (added)
-
tags/1.2.1/templates/holder/form-submit.php (added)
-
tags/1.2.1/templates/holder/submit.php (added)
-
tags/1.2.1/templates/live (added)
-
tags/1.2.1/templates/live/host.php (added)
-
tags/1.2.1/templates/live/room.php (added)
-
tags/1.2.1/templates/partials (added)
-
tags/1.2.1/templates/partials/accept-ready.php (added)
-
tags/1.2.1/templates/partials/account-sidebar.php (added)
-
tags/1.2.1/templates/partials/auction-table.php (added)
-
tags/1.2.1/templates/partials/share-social.php (added)
-
tags/1.2.1/templates/single (added)
-
tags/1.2.1/templates/single/single-auction.php (added)
-
tags/1.2.1/uninstall.php (added)
-
trunk/README.md (modified) (2 diffs)
-
trunk/assets/dist/js/frontend.js (modified) (2 diffs)
-
trunk/changelog.txt (modified) (1 diff)
-
trunk/logicanvas-auctions.php (modified) (1 diff)
-
trunk/readme.txt (modified) (4 diffs)
-
trunk/src/Admin/ActionUI.php (modified) (1 diff)
-
trunk/src/Admin/Menu.php (modified) (2 diffs)
-
trunk/src/Admin/Pages/AuctionsPage.php (modified) (1 diff)
-
trunk/src/Admin/Pages/AwardsPage.php (modified) (1 diff)
-
trunk/src/Admin/Pages/HoldersPage.php (modified) (1 diff)
-
trunk/src/Admin/Pages/SettlementsPage.php (modified) (1 diff)
-
trunk/src/Admin/Pages/SetupWizard.php (modified) (3 diffs)
-
trunk/src/Application/AuctionPresenter.php (modified) (3 diffs)
-
trunk/src/Config.php (modified) (1 diff)
-
trunk/src/Domain/Auction/AuctionService.php (modified) (2 diffs)
-
trunk/src/Domain/Auction/DemoAuction.php (added)
-
trunk/src/Domain/Auction/LiveAuctionService.php (modified) (4 diffs)
-
trunk/src/Domain/Award/AwardService.php (modified) (11 diffs)
-
trunk/src/Domain/Bidding/Bid.php (modified) (1 diff)
-
trunk/src/Domain/Holder/HolderService.php (modified) (11 diffs)
-
trunk/src/Domain/Invitation/AccessService.php (modified) (8 diffs)
-
trunk/src/Domain/Order/HolderOrderService.php (modified) (10 diffs)
-
trunk/src/Domain/Settlement/PayoutRequestService.php (modified) (20 diffs)
-
trunk/src/Domain/Settlement/SettlementService.php (modified) (13 diffs)
-
trunk/src/Frontend/Assets.php (modified) (1 diff)
-
trunk/src/Frontend/Dashboards/AccountProfile.php (modified) (4 diffs)
-
trunk/src/Frontend/Dashboards/BidderDashboard.php (modified) (6 diffs)
-
trunk/src/Frontend/Dashboards/HolderDashboard.php (modified) (2 diffs)
-
trunk/src/Infrastructure/Database/Migrator.php (modified) (1 diff)
-
trunk/src/Infrastructure/Database/RateLimiter.php (modified) (9 diffs)
-
trunk/src/Infrastructure/Database/Schema.php (modified) (1 diff)
-
trunk/src/Infrastructure/Database/WpdbAuctionRepository.php (modified) (8 diffs)
-
trunk/src/Infrastructure/Database/WpdbAuditRepository.php (modified) (4 diffs)
-
trunk/src/Infrastructure/Database/WpdbBidRepository.php (modified) (9 diffs)
-
trunk/src/Infrastructure/Database/WpdbEventRepository.php (modified) (6 diffs)
-
trunk/src/Infrastructure/WooCommerce/CheckoutLock.php (modified) (4 diffs)
-
trunk/src/Infrastructure/WooCommerce/OrderObserver.php (modified) (2 diffs)
-
trunk/src/Infrastructure/WooCommerce/ProductSync.php (modified) (1 diff)
-
trunk/src/Notifications/NotificationService.php (modified) (4 diffs)
-
trunk/src/Privacy/PersonalData.php (modified) (4 diffs)
-
trunk/src/REST/AuctionController.php (modified) (1 diff)
-
trunk/src/REST/MeController.php (modified) (4 diffs)
-
trunk/src/REST/RestController.php (modified) (1 diff)
-
trunk/src/REST/WatchController.php (modified) (2 diffs)
-
trunk/templates/frontend/grid.php (modified) (1 diff)
-
trunk/templates/frontend/single.php (modified) (1 diff)
-
trunk/templates/partials/auction-table.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
logicanvas-auctions/trunk/README.md
r3714634 r3718060 12 12 | --- | --- | 13 13 | **Plugin slug** | `logicanvas-auctions` | 14 | **Version** | 1.2. 0|14 | **Version** | 1.2.1 | 15 15 | **Author** | [Logicanvas.io](https://logicanvas.io) | 16 16 | **Plugin URI** | https://wordpress.org/plugins/logicanvas-auctions/ | … … 634 634 ## Changelog 635 635 636 ### 1.2.1 637 638 - Setup **demo auction**, **Buy Now** on timed lots, and **relist** finished auctions 639 - Clearer catalog empty state for new installs 640 636 641 ### 1.2.0 637 642 -
logicanvas-auctions/trunk/assets/dist/js/frontend.js
r3685679 r3718060 35 35 function request(path, options) { 36 36 options = options || {}; 37 var hdrs = headers(); 38 if (options.headers) { 39 Object.keys(options.headers).forEach(function (k) { 40 hdrs[k] = options.headers[k]; 41 }); 42 } 37 43 return fetch(cfg.restUrl + path, { 38 44 method: options.method || 'GET', 39 headers: h eaders(),45 headers: hdrs, 40 46 credentials: 'same-origin', 41 47 body: options.body ? JSON.stringify(options.body) : undefined … … 938 944 }); 939 945 946 document.querySelectorAll('[data-wcap-buy-now]').forEach(function (btn) { 947 btn.addEventListener('click', function () { 948 var id = btn.getAttribute('data-id'); 949 if (!id) { 950 return; 951 } 952 var confirmMsg = (cfg.i18n && cfg.i18n.buyNowConfirm) || 'Buy now at this fixed price?'; 953 if (!window.confirm(confirmMsg)) { 954 return; 955 } 956 btn.disabled = true; 957 var form = btn.closest('form') || btn.parentElement; 958 var status = form && form.querySelector('.wcap-form-status'); 959 if (status) { 960 status.textContent = '…'; 961 } 962 var key = 'buy-now-' + id + '-' + Date.now() + '-' + Math.random().toString(36).slice(2, 10); 963 request('auctions/' + id + '/buy-now', { 964 method: 'POST', 965 body: { idempotency_key: key }, 966 headers: { 'X-Idempotency-Key': key } 967 }) 968 .then(function (res) { 969 if (status) { 970 status.textContent = (cfg.i18n && cfg.i18n.buyNowOk) || 'Purchase complete.'; 971 } 972 var pay = res && res.auction && res.auction.award && res.auction.award.pay_url; 973 if (pay) { 974 window.location.href = pay; 975 return; 976 } 977 window.location.reload(); 978 }) 979 .catch(function (err) { 980 btn.disabled = false; 981 if (status) { 982 status.textContent = err.message; 983 } else { 984 window.alert(err.message); 985 } 986 }); 987 }); 988 }); 989 990 document.querySelectorAll('[data-wcap-relist]').forEach(function (btn) { 991 btn.addEventListener('click', function () { 992 var id = btn.getAttribute('data-id'); 993 if (!id) { 994 return; 995 } 996 var confirmMsg = (cfg.i18n && cfg.i18n.relistConfirm) || 'Create a new draft copy of this auction?'; 997 if (!window.confirm(confirmMsg)) { 998 return; 999 } 1000 btn.disabled = true; 1001 request('auctions/' + id + '/relist', { method: 'POST', body: {} }) 1002 .then(function (res) { 1003 var url = (res && (res.edit_url || res.admin_url)) || ''; 1004 if (url) { 1005 window.location.href = url; 1006 return; 1007 } 1008 window.location.reload(); 1009 }) 1010 .catch(function (err) { 1011 btn.disabled = false; 1012 window.alert(err.message); 1013 }); 1014 }); 1015 }); 1016 940 1017 var apply = document.querySelector('[data-wcap-apply]'); 941 1018 if (apply) { -
logicanvas-auctions/trunk/changelog.txt
r3714634 r3718060 1 1 === Logicanvas Auctions for WooCommerce — Changelog === 2 3 = 1.2.1 = 4 Release date: 2026-09-29 5 6 * Setup demo auction (create/delete) and clearer next-steps after pages are ready. 7 * Buy Now for timed auctions: ends the lot, creates an award, and sends the buyer to payment. 8 * Relist/duplicate finished auctions (admin list + seller dashboard) as a fresh draft with new dates. 9 * Catalog empty state points admins to Setup / Add Auction. 2 10 3 11 = 1.2.0 = -
logicanvas-auctions/trunk/logicanvas-auctions.php
r3714634 r3718060 4 4 * Plugin URI: https://wordpress.org/plugins/logicanvas-auctions/ 5 5 * Description: Timed and live auctions for WooCommerce. Clear setup, server-side bidding, and winner checkout through your store. 6 * Version: 1.2. 06 * Version: 1.2.1 7 7 * Requires at least: 6.4 8 8 * Requires PHP: 8.1 -
logicanvas-auctions/trunk/readme.txt
r3714634 r3718060 6 6 Tested up to: 7.1 7 7 Requires PHP: 8.1 8 Stable tag: 1.2. 08 Stable tag: 1.2.1 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 33 33 34 34 Pick a look under Auctions → Settings → Appearance (six themes, accent color, radius, density, cards, optional custom CSS). 35 36 After pages are created, Setup can add a **demo auction** so you can try bidding immediately. Timed lots support optional **Buy Now**. Finished lots can be **relisted** as a new draft. 35 37 36 38 = Auction features = … … 304 306 305 307 == Changelog == 308 309 = 1.2.1 = 310 Release date: 2026-09-29 311 312 * Setup demo auction (create/delete) and clearer next-steps after pages are ready. 313 * Buy Now for timed auctions: ends the lot, creates an award, and sends the buyer to payment. 314 * Relist/duplicate finished auctions (admin list + seller dashboard) as a fresh draft with new dates. 315 * Catalog empty state points admins to Setup / Add Auction. 306 316 307 317 = 1.2.0 = … … 350 360 == Upgrade Notice == 351 361 362 = 1.2.1 = 363 Adds Setup demo auction, Buy Now on timed lots, and relist for finished auctions. 364 352 365 = 1.2.0 = 353 Clearer setup, soft defaults (login/shop stay available unless you opt in), and multi-design appearance themes under Auctions → Settings. Existing sites that already used the plugin login page keep that behavior.366 Clearer setup, soft defaults, and appearance themes. Existing sites that already used the plugin login page keep that behavior. 354 367 355 368 = 1.1.0 = -
logicanvas-auctions/trunk/src/Admin/ActionUI.php
r3685679 r3718060 285 285 'reject_holder' => 'dashicons-dismiss', 286 286 'force_close' => 'dashicons-lock', 287 'relist_auction' => 'dashicons-controls-repeat', 287 288 'cancel_auction' => 'dashicons-no-alt', 288 289 'void_bid' => 'dashicons-trash', -
logicanvas-auctions/trunk/src/Admin/Menu.php
r3714634 r3718060 281 281 $result = true; 282 282 break; 283 case 'relist_auction': 284 $new_id = $service->relist( $auction_id, $user_id ); 285 if ( is_wp_error( $new_id ) ) { 286 $result = $new_id; 287 } else { 288 $result = true; 289 $this->flash( 'success', __( 'Auction relisted as a new draft. Opening the editor…', 'logicanvas-auctions' ) ); 290 $edit = get_edit_post_link( (int) $new_id, 'raw' ); 291 wp_safe_redirect( $edit ? (string) $edit : admin_url( 'admin.php?page=wcap-auctions' ) ); 292 exit; 293 } 294 break; 283 295 case 'approve_holder': 284 296 $holders->approve( isset( $_POST['holder_user_id'] ) ? absint( $_POST['holder_user_id'] ) : 0, $user_id ); … … 361 373 'cancel_auction' => __( 'Auction cancelled.', 'logicanvas-auctions' ), 362 374 'force_close' => __( 'Auction close requested.', 'logicanvas-auctions' ), 375 'relist_auction' => __( 'Auction relisted.', 'logicanvas-auctions' ), 363 376 'approve_holder' => __( 'Holder approved.', 'logicanvas-auctions' ), 364 377 'reject_holder' => __( 'Holder rejected.', 'logicanvas-auctions' ), -
logicanvas-auctions/trunk/src/Admin/Pages/AuctionsPage.php
r3685679 r3718060 134 134 ); 135 135 } 136 if ( AuctionState::is_terminal( $state ) ) { 137 ActionUI::button( 138 array( 139 'action' => 'relist_auction', 140 'label' => __( 'Relist', 'logicanvas-auctions' ), 141 'fields' => array( 'auction_id' => $auction->id() ), 142 'confirm' => __( 'Create a new draft copy of this auction (new dates, no bids)?', 'logicanvas-auctions' ), 143 'title' => __( 'Relist auction', 'logicanvas-auctions' ), 144 ) 145 ); 146 } 136 147 echo '</div></td></tr>'; 137 148 } -
logicanvas-auctions/trunk/src/Admin/Pages/AwardsPage.php
r3684440 r3718060 22 22 23 23 global $wpdb; 24 $table = Config::table( Config::TABLE_AWARDS );25 $ rows = QueryCache::remember(26 QueryCache::key( 'admin_awards' ),27 45,28 static function () use ( $wpdb, $table ) {29 wp_cache_get( 'wcap_db', QueryCache::GROUP);30 return $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ), ARRAY_A);31 }32 );24 $table = Config::table( Config::TABLE_AWARDS ); 25 $cache_key = QueryCache::key( 'admin_awards' ); 26 $rows = wp_cache_get( $cache_key, QueryCache::GROUP ); 27 if ( false === $rows || ! is_array( $rows ) ) { 28 $rows = $wpdb->get_results( 29 $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ), ARRAY_A ); 30 $rows = is_array( $rows ) ? $rows : array(); 31 wp_cache_set( $cache_key, $rows, QueryCache::GROUP, 45 ); 32 } 33 33 Screen::open( 34 34 __( 'Awards', 'logicanvas-auctions' ), -
logicanvas-auctions/trunk/src/Admin/Pages/HoldersPage.php
r3685679 r3718060 29 29 if ( false === $rows || ! is_array( $rows ) ) { 30 30 $rows = $wpdb->get_results( 31 $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ),31 $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ), 32 32 ARRAY_A 33 33 ); -
logicanvas-auctions/trunk/src/Admin/Pages/SettlementsPage.php
r3684440 r3718060 29 29 30 30 global $wpdb; 31 $table = Config::table( Config::TABLE_SETTLEMENTS ); 32 $rows = QueryCache::remember( 33 QueryCache::key( 'admin_settlements' ), 34 45, 35 static function () use ( $wpdb, $table ) { 36 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 37 return $wpdb->get_results( $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ), ARRAY_A ); 38 } 39 ); 40 $rows = is_array( $rows ) ? $rows : array(); 31 $table = Config::table( Config::TABLE_SETTLEMENTS ); 32 $cache_key = QueryCache::key( 'admin_settlements' ); 33 $rows = wp_cache_get( $cache_key, QueryCache::GROUP ); 34 if ( false === $rows || ! is_array( $rows ) ) { 35 $rows = $wpdb->get_results( 36 $wpdb->prepare( 'SELECT * FROM %i ORDER BY id DESC LIMIT 100', $table ), ARRAY_A ); 37 $rows = is_array( $rows ) ? $rows : array(); 38 wp_cache_set( $cache_key, $rows, QueryCache::GROUP, 45 ); 39 } 41 40 42 41 $pending_requests = 0; -
logicanvas-auctions/trunk/src/Admin/Pages/SetupWizard.php
r3714634 r3718060 13 13 use LogicanvasAuctions\Admin\Settings; 14 14 use LogicanvasAuctions\Config; 15 use LogicanvasAuctions\Frontend\PluginPages; 15 16 16 17 final class SetupWizard { … … 33 34 } 34 35 36 if ( isset( $_POST['wcap_demo_create'] ) ) { 37 check_admin_referer( 'wcap_demo_auction' ); 38 $result = \LogicanvasAuctions\Domain\Auction\DemoAuction::create( get_current_user_id() ); 39 if ( is_wp_error( $result ) ) { 40 echo '<div class="notice notice-error"><p>' . esc_html( $result->get_error_message() ) . '</p></div>'; 41 } else { 42 $view = get_permalink( (int) $result ); 43 echo '<div class="notice notice-success"><p>' . esc_html__( 'Demo auction created and published. Try bidding as another user, or open it below.', 'logicanvas-auctions' ); 44 if ( $view ) { 45 echo ' <a href="' . esc_url( $view ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'View demo lot', 'logicanvas-auctions' ) . '</a>'; 46 } 47 echo '</p></div>'; 48 } 49 } 50 51 if ( isset( $_POST['wcap_demo_delete'] ) ) { 52 check_admin_referer( 'wcap_demo_auction' ); 53 $result = \LogicanvasAuctions\Domain\Auction\DemoAuction::delete( get_current_user_id() ); 54 if ( is_wp_error( $result ) ) { 55 echo '<div class="notice notice-error"><p>' . esc_html( $result->get_error_message() ) . '</p></div>'; 56 } else { 57 echo '<div class="notice notice-success"><p>' . esc_html__( 'Demo auction moved to trash.', 'logicanvas-auctions' ) . '</p></div>'; 58 } 59 } 60 35 61 $pages = get_option( Config::OPTION_PAGES, array() ); 36 62 $ready = is_array( $pages ) && ! empty( $pages['archive'] ); 63 $demo = \LogicanvasAuctions\Domain\Auction\DemoAuction::exists(); 37 64 38 65 Screen::open( … … 93 120 echo '</form>'; 94 121 Screen::panel_close(); 122 123 if ( $ready || $done ) { 124 Screen::panel_open( '', __( 'Next steps', 'logicanvas-auctions' ) ); 125 $archive = PluginPages::url( 'archive' ); 126 echo '<ol class="wcap-setup-steps">'; 127 if ( $archive ) { 128 echo '<li><a href="' . esc_url( $archive ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'View auction catalog', 'logicanvas-auctions' ) . '</a></li>'; 129 } 130 echo '<li><a href="' . esc_url( admin_url( 'post-new.php?post_type=' . Config::CPT ) ) . '">' . esc_html__( 'Add a real auction', 'logicanvas-auctions' ) . '</a></li>'; 131 echo '<li>' . esc_html__( 'Optional: create a demo lot below so you can try bidding immediately.', 'logicanvas-auctions' ) . '</li>'; 132 echo '</ol>'; 133 134 echo '<form method="post" class="wcap-demo-form">'; 135 wp_nonce_field( 'wcap_demo_auction' ); 136 if ( $demo ) { 137 $demo_id = \LogicanvasAuctions\Domain\Auction\DemoAuction::current_id(); 138 $demo_url = get_permalink( $demo_id ); 139 echo '<p>' . esc_html__( 'A demo auction is ready.', 'logicanvas-auctions' ); 140 if ( $demo_url ) { 141 echo ' <a href="' . esc_url( $demo_url ) . '" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Open it', 'logicanvas-auctions' ) . '</a>'; 142 } 143 echo ' · <a href="' . esc_url( get_edit_post_link( $demo_id ) ?: '#' ) . '">' . esc_html__( 'Edit', 'logicanvas-auctions' ) . '</a>'; 144 echo '</p>'; 145 echo '<p><button class="button" name="wcap_demo_delete" value="1">' . esc_html__( 'Delete demo auction', 'logicanvas-auctions' ) . '</button></p>'; 146 } else { 147 echo '<p class="description">' . esc_html__( 'Creates one public timed lot with Buy Now, starting now and ending in 24 hours. Marked as demo; safe to trash.', 'logicanvas-auctions' ) . '</p>'; 148 echo '<p><button class="button button-primary" name="wcap_demo_create" value="1">' . esc_html__( 'Create demo auction', 'logicanvas-auctions' ) . '</button></p>'; 149 } 150 echo '</form>'; 151 Screen::panel_close(); 152 } 95 153 96 154 if ( is_array( $pages ) && $pages ) { -
logicanvas-auctions/trunk/src/Application/AuctionPresenter.php
r3685679 r3718060 68 68 'is_leading' => $viewer_id > 0 && $auction->current_leader_id() === $viewer_id, 69 69 'can_bid' => $viewer_id > 0 && ! $auction->is_holder( $viewer_id ) && $auction->accepts_bids(), 70 'can_buy_now' => $this->can_buy_now( $auction, $viewer_id ), 70 71 'can_accept_bid' => $this->can_accept_highest( $auction, $viewer_id ), 71 72 'can_edit' => $this->can_edit( $auction, $viewer_id ), … … 78 79 'realtime_mode' => (string) Settings::get()['realtime_mode'], 79 80 ); 81 82 $buy_now = $auction->buy_now_amount(); 83 if ( $buy_now && $buy_now->greater_than( $auction->current_amount() ) ) { 84 $payload['buy_now_price'] = $buy_now->to_rest(); 85 } 80 86 81 87 if ( 'always' === $display && $reserve ) { … … 197 203 } 198 204 205 private function can_buy_now( Auction $auction, int $viewer_id ): bool { 206 if ( $viewer_id < 1 || ! $auction->is_timed() || ! $auction->accepts_bids() ) { 207 return false; 208 } 209 if ( $auction->is_holder( $viewer_id ) || ! user_can( $viewer_id, \LogicanvasAuctions\Config::CAP_BID ) ) { 210 return false; 211 } 212 $buy = $auction->buy_now_amount(); 213 if ( ! $buy || ! $buy->greater_than( $auction->current_amount() ) ) { 214 return false; 215 } 216 return true; 217 } 218 199 219 /** 200 220 * @return array{content:string,excerpt:string} -
logicanvas-auctions/trunk/src/Config.php
r3714634 r3718060 19 19 public const REVIEW_URI = 'https://wordpress.org/support/plugin/logicanvas-auctions/reviews/#new-post'; 20 20 public const SLUG = 'logicanvas-auctions'; 21 public const VERSION = '1.2. 0';21 public const VERSION = '1.2.1'; 22 22 public const DB_VERSION = '1.0.2'; 23 23 public const TEXT_DOMAIN = 'logicanvas-auctions'; -
logicanvas-auctions/trunk/src/Domain/Auction/AuctionService.php
r3685679 r3718060 298 298 $patch['reserve_amount'] = '' === $reserve ? null : Money::from_string( $reserve, $auction->currency() )->amount(); 299 299 } 300 if ( isset( $input['buy_now'] ) ) { 301 $buy = trim( (string) $input['buy_now'] ); 302 $patch['buy_now_amount'] = '' === $buy ? null : Money::from_string( $buy, $auction->currency() )->amount(); 303 } 300 304 } 301 305 … … 728 732 return $ts ? gmdate( 'Y-m-d H:i:s', $ts ) : $this->clock->utc_mysql(); 729 733 } 734 735 /** 736 * Duplicate a finished auction into a new lot (fresh state, no bids/awards). 737 * 738 * @return int|WP_Error New auction ID. 739 */ 740 public function relist( int $source_id, int $user_id ) { 741 $source = $this->auctions->find( $source_id ); 742 if ( ! $source ) { 743 return new WP_Error( 'not_found', __( 'Auction not found.', 'logicanvas-auctions' ) ); 744 } 745 746 if ( $source->holder_id() !== $user_id && ! user_can( $user_id, Config::CAP_MODERATE_AUCTIONS ) ) { 747 return new WP_Error( 'forbidden', __( 'You cannot relist this auction.', 'logicanvas-auctions' ) ); 748 } 749 750 if ( ! user_can( $user_id, Config::CAP_CREATE_AUCTIONS ) && ! user_can( $user_id, Config::CAP_MODERATE_AUCTIONS ) ) { 751 return new WP_Error( 'forbidden', __( 'You cannot create auctions.', 'logicanvas-auctions' ) ); 752 } 753 754 $relistable = array( 755 AuctionState::UNSOLD, 756 AuctionState::COMPLETED, 757 AuctionState::CANCELLED, 758 AuctionState::RESERVE_NOT_MET, 759 AuctionState::PAYMENT_DEFAULTED, 760 ); 761 if ( ! in_array( $source->state(), $relistable, true ) ) { 762 return new WP_Error( 'invalid_state', __( 'Only finished auctions can be relisted.', 'logicanvas-auctions' ) ); 763 } 764 765 $post = get_post( $source_id ); 766 if ( ! $post ) { 767 return new WP_Error( 'not_found', __( 'Auction post missing.', 'logicanvas-auctions' ) ); 768 } 769 770 $settings = Settings::get(); 771 $duration = max( 3600, (int) ( $settings['timed_default_duration'] ?? ( DAY_IN_SECONDS * 7 ) ) ); 772 $now_ts = $this->clock->timestamp(); 773 $start = gmdate( 'Y-m-d H:i:s', $now_ts ); 774 $end = $source->is_timed() ? gmdate( 'Y-m-d H:i:s', $now_ts + $duration ) : null; 775 776 $buy_now = $source->buy_now_amount(); 777 $reserve = $source->reserve_amount(); 778 $row = $source->to_array(); 779 780 $input = array( 781 'title' => $post->post_title, 782 'description' => $post->post_content, 783 'short_description' => $post->post_excerpt, 784 'type' => $source->type(), 785 'visibility' => $source->visibility(), 786 'product_source' => 'new', 787 'condition' => (string) get_post_meta( $source_id, '_wcap_condition', true ), 788 'starting_price' => $source->starting_amount()->amount(), 789 'reserve_price' => $reserve ? $reserve->amount() : '', 790 'min_increment' => $source->min_increment()->amount(), 791 'buy_now' => $buy_now ? $buy_now->amount() : '', 792 'start_at_utc' => $start, 793 'end_at_utc' => $end ?? '', 794 'fulfilment_type' => sanitize_key( (string) ( $row['fulfilment_type'] ?? 'shipping' ) ), 795 'fulfilment_notes' => (string) get_post_meta( $source_id, '_wcap_fulfilment_notes', true ), 796 'tax_class' => sanitize_text_field( (string) ( $row['tax_class'] ?? '' ) ), 797 'shipping_class' => sanitize_text_field( (string) ( $row['shipping_class'] ?? '' ) ), 798 'payment_deadline_hours' => (int) ( $row['payment_deadline_hours'] ?? 48 ), 799 'proxy_enabled' => ! empty( $row['proxy_enabled'] ), 800 'featured_image_id' => (int) get_post_thumbnail_id( $source_id ), 801 'gallery_ids' => get_post_meta( $source_id, '_wcap_gallery', true ), 802 ); 803 804 $terms = wp_get_object_terms( $source_id, Config::TAXONOMY_CAT, array( 'fields' => 'ids' ) ); 805 if ( is_array( $terms ) && ! empty( $terms[0] ) ) { 806 $input['category_id'] = (int) $terms[0]; 807 } 808 809 $new_id = $this->create( $user_id, $input ); 810 if ( is_wp_error( $new_id ) ) { 811 return $new_id; 812 } 813 814 update_post_meta( (int) $new_id, '_wcap_relisted_from', $source_id ); 815 816 /** 817 * Fires after an auction is relisted as a new lot. 818 * 819 * @param int $new_id New auction ID. 820 * @param int $source_id Source auction ID. 821 * @param int $user_id Actor. 822 */ 823 do_action( 'wcap_auction_relisted', (int) $new_id, $source_id, $user_id ); 824 825 return (int) $new_id; 826 } 730 827 } -
logicanvas-auctions/trunk/src/Domain/Auction/LiveAuctionService.php
r3684440 r3718060 114 114 global $wpdb; 115 115 116 $now = gmdate( 'Y-m-d H:i:s' ); 116 $now = gmdate( 'Y-m-d H:i:s' ); 117 $cache_key = QueryCache::key( 'participant_hb', $auction_id, $user_id ); 118 wp_cache_get( $cache_key, QueryCache::GROUP ); 117 119 $wpdb->query( 118 120 $wpdb->prepare( … … 127 129 ) 128 130 ); 131 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 129 132 130 133 QueryCache::bust_auction( $auction_id ); … … 141 144 15, 142 145 static function () use ( $wpdb, $table, $auction_id, $cutoff ) { 143 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 144 return $wpdb->get_var( 146 $cache_key = 'wcap_db_local'; 147 wp_cache_get( $cache_key, QueryCache::GROUP ); 148 $_result = $wpdb->get_var( 145 149 $wpdb->prepare( 146 150 'SELECT COUNT(*) FROM %i WHERE auction_id = %d AND last_seen_utc >= %s', … … 150 154 ) 151 155 ); 156 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 157 return $_result; 152 158 } 153 159 ); -
logicanvas-auctions/trunk/src/Domain/Award/AwardService.php
r3684440 r3718060 243 243 } 244 244 245 /** 246 * Purchase at the fixed Buy Now price (timed auctions only). Ends the auction and creates an award. 247 * 248 * @return true|\WP_Error 249 */ 250 public function buy_now( int $auction_id, int $user_id, string $idempotency_key = '' ) { 251 $key = sanitize_text_field( $idempotency_key ); 252 if ( '' === $key ) { 253 $key = 'buy-now-' . $auction_id . '-' . $user_id . '-' . wp_generate_password( 12, false, false ); 254 } 255 $key = substr( $key, 0, 64 ); 256 257 if ( $user_id < 1 ) { 258 return new \WP_Error( 'unauthenticated', __( 'You must be logged in to buy now.', 'logicanvas-auctions' ), array( 'status' => 401 ) ); 259 } 260 261 if ( ! user_can( $user_id, Config::CAP_BID ) ) { 262 return new \WP_Error( 'forbidden', __( 'Your account cannot purchase auction lots.', 'logicanvas-auctions' ), array( 'status' => 403 ) ); 263 } 264 265 $auction = $this->auctions->find( $auction_id ); 266 if ( ! $auction ) { 267 return new \WP_Error( 'not_found', __( 'Auction not found.', 'logicanvas-auctions' ), array( 'status' => 404 ) ); 268 } 269 270 if ( ! $auction->is_timed() ) { 271 return new \WP_Error( 'invalid_type', __( 'Buy Now is only available on timed auctions.', 'logicanvas-auctions' ), array( 'status' => 400 ) ); 272 } 273 274 $buy_now = $auction->buy_now_amount(); 275 if ( ! $buy_now ) { 276 return new \WP_Error( 'unavailable', __( 'This auction does not have a Buy Now price.', 'logicanvas-auctions' ), array( 'status' => 400 ) ); 277 } 278 279 if ( $auction->is_holder( $user_id ) ) { 280 return new \WP_Error( 'forbidden', __( 'You cannot buy your own auction.', 'logicanvas-auctions' ), array( 'status' => 403 ) ); 281 } 282 283 $existing = $this->for_auction( $auction_id ); 284 if ( $existing && self::CANCELLED !== $existing['status'] ) { 285 if ( (int) $existing['winner_id'] === $user_id ) { 286 return true; 287 } 288 return new \WP_Error( 'closed', __( 'This auction is already sold.', 'logicanvas-auctions' ), array( 'status' => 409 ) ); 289 } 290 291 $replay = $this->bids->find_by_idempotency( $auction_id, $key ); 292 if ( $replay && $replay->bidder_id() === $user_id && Bid::TYPE_BUY_NOW === $replay->type() ) { 293 return true; 294 } 295 296 $lock = 'wcap_close_' . $auction_id; 297 if ( ! $this->acquire( $lock ) ) { 298 return new \WP_Error( 'busy', __( 'This auction is already closing. Please wait a moment.', 'logicanvas-auctions' ), array( 'status' => 409 ) ); 299 } 300 301 try { 302 Transaction::run( 303 function () use ( $auction_id, $user_id, $key ) { 304 $auction = $this->auctions->find_for_update( $auction_id ); 305 if ( ! $auction || ! $auction->is_timed() ) { 306 throw new \RuntimeException( 'not_found' ); 307 } 308 309 if ( ! in_array( $auction->state(), array( AuctionState::ACTIVE ), true ) ) { 310 throw new \RuntimeException( 'invalid_state' ); 311 } 312 313 $buy_now = $auction->buy_now_amount(); 314 if ( ! $buy_now ) { 315 throw new \RuntimeException( 'unavailable' ); 316 } 317 318 if ( ! $buy_now->greater_than( $auction->current_amount() ) ) { 319 throw new \RuntimeException( 'price_passed' ); 320 } 321 322 $end = $auction->end_at_utc() ? strtotime( $auction->end_at_utc() . ' UTC' ) : 0; 323 if ( $end && $this->clock->timestamp() >= $end ) { 324 throw new \RuntimeException( 'ended' ); 325 } 326 327 if ( $auction->is_holder( $user_id ) ) { 328 throw new \RuntimeException( 'self' ); 329 } 330 331 $access = new \LogicanvasAuctions\Domain\Invitation\AccessService(); 332 if ( ! $access->can_view( $auction, $user_id, '' ) ) { 333 throw new \RuntimeException( 'access' ); 334 } 335 336 $holder = new \LogicanvasAuctions\Domain\Holder\HolderService(); 337 if ( $holder->is_suspended_user( $user_id ) ) { 338 throw new \RuntimeException( 'suspended' ); 339 } 340 341 $existing = $this->for_auction( $auction_id ); 342 if ( $existing && self::CANCELLED !== $existing['status'] ) { 343 return true; 344 } 345 346 $replay = $this->bids->find_by_idempotency( $auction_id, $key ); 347 if ( $replay ) { 348 return true; 349 } 350 351 $now = $this->clock->utc_mysql(); 352 $bid_id = $this->bids->insert( 353 array( 354 'auction_id' => $auction_id, 355 'bidder_id' => $user_id, 356 'amount' => $buy_now->amount(), 357 'currency' => $auction->currency(), 358 'type' => Bid::TYPE_BUY_NOW, 359 'max_amount' => null, 360 'status' => Bid::STATUS_ACCEPTED, 361 'idempotency_key' => $key, 362 'ip_hash' => null, 363 'user_agent_hash' => null, 364 'created_at_utc' => $now, 365 ) 366 ); 367 368 $seq = $auction->sequence() + 1; 369 $this->auctions->update_state( 370 $auction_id, 371 array( 372 'current_amount' => $buy_now->amount(), 373 'current_leader_id' => $user_id, 374 'bid_count' => $auction->bid_count() + 1, 375 'sequence' => $seq, 376 'updated_at_utc' => $now, 377 ) 378 ); 379 380 $this->events->insert( 381 array( 382 'auction_id' => $auction_id, 383 'sequence' => $seq, 384 'event_type' => 'buy_now', 385 'actor_id' => $user_id, 386 'actor_type' => 'user', 387 'payload' => wp_json_encode( 388 array( 389 'bid_id' => $bid_id, 390 'amount' => $buy_now->amount(), 391 ) 392 ), 393 'correlation_key' => $key, 394 'created_at_utc' => $now, 395 ) 396 ); 397 398 $bid = $this->bids->find( $bid_id ); 399 if ( ! $bid ) { 400 throw new \RuntimeException( 'bid_missing' ); 401 } 402 403 $auction = $this->auctions->find_for_update( $auction_id ); 404 if ( ! $auction ) { 405 throw new \RuntimeException( 'not_found' ); 406 } 407 408 $reason = 'Buy Now purchase'; 409 $this->auction_service->transition( $auction_id, AuctionState::CLOSING, $user_id, 'user', $reason, 'buy-now-' . $auction_id ); 410 $this->auction_service->transition( $auction_id, AuctionState::ENDED, $user_id, 'user', $reason, 'buy-now-ended-' . $auction_id ); 411 412 $award_id = $this->create_award( $auction, $bid ); 413 $this->auction_service->transition( $auction_id, AuctionState::PAYMENT_PENDING, $user_id, 'user', 'Winner awarded via Buy Now', 'buy-now-award-' . $auction_id ); 414 415 $this->auctions->update_state( 416 $auction_id, 417 array( 418 'award_id' => $award_id, 419 'updated_at_utc' => $this->clock->utc_mysql(), 420 ) 421 ); 422 423 $hours = $auction->payment_deadline_hours(); 424 $deadline = gmdate( 'Y-m-d H:i:s', $this->clock->timestamp() + ( $hours * HOUR_IN_SECONDS ) ); 425 $this->scheduler->unschedule_close( $auction_id ); 426 $this->scheduler->schedule_payment_deadline( $award_id, $auction_id, $deadline ); 427 428 ( new SettlementService() )->create_pending_for_award( $auction_id, $award_id ); 429 430 do_action( 'wcap_award_created', $auction_id, $award_id, $user_id ); 431 do_action( 'wcap_auction_closed', $auction_id, 'buy_now' ); 432 do_action( 'wcap_buy_now_completed', $auction_id, $award_id, $user_id ); 433 434 return true; 435 } 436 ); 437 } catch ( \Throwable $e ) { 438 $code = $e->getMessage(); 439 $map = array( 440 'invalid_state' => array( 'invalid_state', __( 'This auction is not open for Buy Now.', 'logicanvas-auctions' ), 400 ), 441 'unavailable' => array( 'unavailable', __( 'This auction does not have a Buy Now price.', 'logicanvas-auctions' ), 400 ), 442 'price_passed' => array( 'price_passed', __( 'Bidding has passed the Buy Now price.', 'logicanvas-auctions' ), 409 ), 443 'ended' => array( 'ended', __( 'This auction has already ended.', 'logicanvas-auctions' ), 409 ), 444 'self' => array( 'forbidden', __( 'You cannot buy your own auction.', 'logicanvas-auctions' ), 403 ), 445 'access' => array( 'forbidden', __( 'You do not have access to this auction.', 'logicanvas-auctions' ), 403 ), 446 'suspended' => array( 'forbidden', __( 'Your account cannot purchase auction lots.', 'logicanvas-auctions' ), 403 ), 447 'not_found' => array( 'not_found', __( 'Auction not found.', 'logicanvas-auctions' ), 404 ), 448 ); 449 $err = $map[ $code ] ?? array( 'buy_now_failed', __( 'Could not complete Buy Now. Please try again.', 'logicanvas-auctions' ), 400 ); 450 return new \WP_Error( $err[0], $err[1], array( 'status' => $err[2] ) ); 451 } finally { 452 $this->release( $lock ); 453 } 454 455 return true; 456 } 457 245 458 public function mark_unsold( int $auction_id, int $actor_id, string $reason ): void { 246 459 $auction = $this->auctions->find( $auction_id ); … … 266 479 60, 267 480 static function () use ( $wpdb, $table, $award_id ) { 268 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 269 return $wpdb->get_row( 481 $cache_key = 'wcap_db_local'; 482 wp_cache_get( $cache_key, QueryCache::GROUP ); 483 $_result = $wpdb->get_row( 270 484 $wpdb->prepare( 271 485 'SELECT * FROM %i WHERE id = %d', … … 275 489 ARRAY_A 276 490 ); 491 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 492 return $_result; 277 493 } 278 494 ); … … 292 508 60, 293 509 static function () use ( $wpdb, $table, $auction_id ) { 294 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 295 return $wpdb->get_row( 510 $cache_key = 'wcap_db_local'; 511 wp_cache_get( $cache_key, QueryCache::GROUP ); 512 $_result = $wpdb->get_row( 296 513 $wpdb->prepare( 297 514 'SELECT * FROM %i WHERE auction_id = %d ORDER BY id DESC LIMIT 1', … … 301 518 ARRAY_A 302 519 ); 520 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 521 return $_result; 303 522 } 304 523 ); … … 314 533 return; 315 534 } 535 536 $cache_key = QueryCache::key( 'award_mark_paid', $award_id, $order_id ); 537 wp_cache_get( $cache_key, QueryCache::GROUP ); 316 538 317 539 if ( self::PAID !== $award['status'] ) { … … 336 558 } 337 559 560 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 338 561 QueryCache::bust_auction( (int) $award['auction_id'] ); 339 562 … … 388 611 389 612 global $wpdb; 613 $cache_key = QueryCache::key( 'award_expire', $award_id ); 614 wp_cache_get( $cache_key, QueryCache::GROUP ); 390 615 $wpdb->update( 391 616 Config::table( Config::TABLE_AWARDS ), … … 396 621 array( 'id' => $award_id ) 397 622 ); 623 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 398 624 399 625 QueryCache::bust_auction( (int) $award['auction_id'] ); … … 414 640 $deadline = gmdate( 'Y-m-d H:i:s', $this->clock->timestamp() + ( $auction->payment_deadline_hours() * HOUR_IN_SECONDS ) ); 415 641 $now = $this->clock->utc_mysql(); 642 643 $cache_key = QueryCache::key( 'award_create', $auction->id(), $key ); 644 wp_cache_get( $cache_key, QueryCache::GROUP ); 416 645 417 646 $wpdb->insert( … … 431 660 ); 432 661 662 $award_id = (int) $wpdb->insert_id; 663 wp_cache_set( $cache_key, $award_id, QueryCache::GROUP, 30 ); 433 664 QueryCache::bust_auction( $auction->id() ); 434 665 435 return (int) $wpdb->insert_id;666 return $award_id; 436 667 } 437 668 -
logicanvas-auctions/trunk/src/Domain/Bidding/Bid.php
r3684440 r3718060 20 20 public const TYPE_PROXY = 'proxy'; 21 21 public const TYPE_PROXY_FILL = 'proxy_fill'; 22 public const TYPE_BUY_NOW = 'buy_now'; 22 23 23 24 /** -
logicanvas-auctions/trunk/src/Domain/Holder/HolderService.php
r3684440 r3718060 26 26 global $wpdb; 27 27 28 $existing = $this->for_user( $user_id ); 29 $now = gmdate( 'Y-m-d H:i:s' ); 28 $existing = $this->for_user( $user_id ); 29 $now = gmdate( 'Y-m-d H:i:s' ); 30 $cache_key = QueryCache::key( 'holder_apply', $user_id ); 31 wp_cache_get( $cache_key, QueryCache::GROUP ); 30 32 31 33 if ( $existing ) { … … 40 42 array( 'user_id' => $user_id ) 41 43 ); 44 wp_cache_set( $cache_key, (int) $existing['id'], QueryCache::GROUP, 30 ); 42 45 QueryCache::delete( QueryCache::key( 'holder', $user_id ) ); 43 46 QueryCache::flush_group(); … … 57 60 ); 58 61 62 $id = (int) $wpdb->insert_id; 63 wp_cache_set( $cache_key, $id, QueryCache::GROUP, 30 ); 59 64 QueryCache::flush_group(); 60 65 61 return (int) $wpdb->insert_id;66 return $id; 62 67 } 63 68 … … 77 82 global $wpdb; 78 83 84 $cache_key = QueryCache::key( 'holder_reject', $user_id ); 85 wp_cache_get( $cache_key, QueryCache::GROUP ); 86 79 87 $wpdb->update( 80 88 Config::table( Config::TABLE_HOLDERS ), … … 88 96 array( 'user_id' => $user_id ) 89 97 ); 98 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 90 99 QueryCache::flush_group(); 91 100 do_action( 'wcap_holder_rejected', $user_id ); … … 94 103 public function suspend( int $user_id, int $reviewer_id, string $notes = '' ): void { 95 104 global $wpdb; 105 106 $cache_key = QueryCache::key( 'holder_suspend', $user_id ); 107 wp_cache_get( $cache_key, QueryCache::GROUP ); 96 108 97 109 $wpdb->update( … … 106 118 array( 'user_id' => $user_id ) 107 119 ); 120 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 108 121 QueryCache::flush_group(); 109 122 } … … 142 155 60, 143 156 static function () use ( $wpdb, $table, $user_id ) { 144 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 145 return $wpdb->get_row( 157 $cache_key = 'wcap_db_local'; 158 wp_cache_get( $cache_key, QueryCache::GROUP ); 159 $_result = $wpdb->get_row( 146 160 $wpdb->prepare( 147 161 'SELECT * FROM %i WHERE user_id = %d', … … 151 165 ARRAY_A 152 166 ); 167 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 168 return $_result; 153 169 } 154 170 ); … … 159 175 private function set_status( int $user_id, string $status, int $reviewer_id ): void { 160 176 global $wpdb; 177 178 $cache_key = QueryCache::key( 'holder_status', $user_id, $status ); 179 wp_cache_get( $cache_key, QueryCache::GROUP ); 161 180 162 181 $wpdb->update( … … 170 189 array( 'user_id' => $user_id ) 171 190 ); 191 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 172 192 QueryCache::flush_group(); 173 193 } -
logicanvas-auctions/trunk/src/Domain/Invitation/AccessService.php
r3684440 r3718060 63 63 $exp = $ttl_seconds ? gmdate( 'Y-m-d H:i:s', time() + $ttl_seconds ) : null; 64 64 65 $cache_key = QueryCache::key( 'invite_create', $auction_id, $hash ); 66 wp_cache_get( $cache_key, QueryCache::GROUP ); 67 65 68 $wpdb->insert( 66 69 Config::table( Config::TABLE_INVITATIONS ), … … 78 81 ); 79 82 83 wp_cache_set( $cache_key, (int) $wpdb->insert_id, QueryCache::GROUP, 30 ); 80 84 QueryCache::bust_auction( $auction_id ); 81 85 … … 86 90 global $wpdb; 87 91 92 $cache_key = QueryCache::key( 'invite_revoke', $invitation_id ); 93 wp_cache_get( $cache_key, QueryCache::GROUP ); 94 88 95 $wpdb->update( 89 96 Config::table( Config::TABLE_INVITATIONS ), … … 92 99 ); 93 100 101 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 94 102 QueryCache::flush_group(); 95 103 } … … 121 129 60, 122 130 static function () use ( $wpdb, $table, $auction_id, $user_id ) { 123 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 124 return $wpdb->get_row( 125 $wpdb->prepare( 131 $cache_key = 'wcap_db_local'; 132 wp_cache_get( $cache_key, QueryCache::GROUP ); 133 $_result = $wpdb->get_row( 134 $wpdb->prepare( 126 135 'SELECT * FROM %i WHERE auction_id = %d AND user_id = %d AND revoked_at_utc IS NULL', 127 136 $table, … … 131 140 ARRAY_A 132 141 ); 142 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 143 return $_result; 133 144 } 134 145 ); … … 139 150 60, 140 151 static function () use ( $wpdb, $table, $auction_id, $hash ) { 141 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 142 return $wpdb->get_row( 143 $wpdb->prepare( 152 $cache_key = 'wcap_db_local'; 153 wp_cache_get( $cache_key, QueryCache::GROUP ); 154 $_result = $wpdb->get_row( 155 $wpdb->prepare( 144 156 'SELECT * FROM %i WHERE auction_id = %d AND token_hash = %s AND revoked_at_utc IS NULL', 145 157 $table, … … 149 161 ARRAY_A 150 162 ); 163 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 164 return $_result; 151 165 } 152 166 ); -
logicanvas-auctions/trunk/src/Domain/Order/HolderOrderService.php
r3684440 r3718060 41 41 45, 42 42 static function () use ( $wpdb, $settle_t, $award_t, $state_t, $holder_id ) { 43 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 44 return $wpdb->get_results( 43 $cache_key = 'wcap_db_local'; 44 wp_cache_get( $cache_key, QueryCache::GROUP ); 45 $_result = $wpdb->get_results( 45 46 $wpdb->prepare( 46 47 'SELECT s.id AS settlement_id, s.auction_id, s.award_id, s.gross_amount, s.commission_amount, s.net_amount, s.currency, s.payout_status, … … 60 61 ARRAY_A 61 62 ); 63 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 64 return $_result; 62 65 } 63 66 ); … … 111 114 45, 112 115 static function () use ( $wpdb, $award_t, $state_t, $holder_id ) { 113 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 114 return $wpdb->get_results( 116 $cache_key = 'wcap_db_local'; 117 wp_cache_get( $cache_key, QueryCache::GROUP ); 118 $_result = $wpdb->get_results( 115 119 $wpdb->prepare( 116 120 'SELECT a.id AS award_id, a.auction_id, a.order_id, a.winner_id, a.status AS award_status, a.amount, a.currency … … 126 130 ARRAY_A 127 131 ); 132 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 133 return $_result; 128 134 } 129 135 ); … … 322 328 30, 323 329 static function () use ( $wpdb, $state_t, $award_t, $holder_id ) { 324 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 325 return $wpdb->get_results( 330 $cache_key = 'wcap_db_local'; 331 wp_cache_get( $cache_key, QueryCache::GROUP ); 332 $_result = $wpdb->get_results( 326 333 $wpdb->prepare( 327 334 'SELECT a.id AS award_id, a.order_id, st.auction_id, st.state, st.order_id AS state_order_id … … 340 347 ARRAY_A 341 348 ); 349 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 350 return $_result; 342 351 } 343 352 ); … … 378 387 60, 379 388 static function () use ( $wpdb, $award_t, $auction_id ) { 380 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 381 return $wpdb->get_var( 389 $cache_key = 'wcap_db_local'; 390 wp_cache_get( $cache_key, QueryCache::GROUP ); 391 $_result = $wpdb->get_var( 382 392 $wpdb->prepare( 383 393 'SELECT order_id FROM %i WHERE auction_id = %d AND order_id > 0 ORDER BY id DESC LIMIT 1', … … 386 396 ) 387 397 ); 398 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 399 return $_result; 388 400 } 389 401 ); … … 397 409 60, 398 410 static function () use ( $wpdb, $state_t, $auction_id ) { 399 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 400 return $wpdb->get_var( 411 $cache_key = 'wcap_db_local'; 412 wp_cache_get( $cache_key, QueryCache::GROUP ); 413 $_result = $wpdb->get_var( 401 414 $wpdb->prepare( 402 415 'SELECT order_id FROM %i WHERE auction_id = %d AND order_id > 0 LIMIT 1', … … 405 418 ) 406 419 ); 420 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 421 return $_result; 407 422 } 408 423 ); -
logicanvas-auctions/trunk/src/Domain/Settlement/PayoutRequestService.php
r3684440 r3718060 126 126 45, 127 127 static function () use ( $wpdb, $settle_t, $holder_id ) { 128 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 129 return $wpdb->get_results( 128 $cache_key = 'wcap_db_local'; 129 wp_cache_get( $cache_key, QueryCache::GROUP ); 130 $_result = $wpdb->get_results( 130 131 $wpdb->prepare( 131 132 'SELECT net_amount, released_amount, currency FROM %i WHERE holder_id = %d AND payout_status = %s', … … 136 137 ARRAY_A 137 138 ); 139 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 140 return $_result; 138 141 } 139 142 ); … … 159 162 45, 160 163 static function () use ( $wpdb, $payout_t, $holder_id ) { 161 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 162 return $wpdb->get_var( 164 $cache_key = 'wcap_db_local'; 165 wp_cache_get( $cache_key, QueryCache::GROUP ); 166 $_result = $wpdb->get_var( 163 167 $wpdb->prepare( 164 168 'SELECT COALESCE(SUM(amount), 0) FROM %i WHERE holder_id = %d AND status IN (%s, %s)', … … 169 173 ) 170 174 ); 175 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 176 return $_result; 171 177 } 172 178 ); … … 234 240 235 241 global $wpdb; 242 $cache_key = QueryCache::key( 'payout_request', $holder_id, $amount ); 243 wp_cache_get( $cache_key, QueryCache::GROUP ); 236 244 $inserted = $wpdb->insert( 237 245 Config::table( Config::TABLE_PAYOUT_REQUESTS ), … … 254 262 } 255 263 264 wp_cache_set( $cache_key, (int) $wpdb->insert_id, QueryCache::GROUP, 30 ); 256 265 QueryCache::flush_group(); 257 266 … … 284 293 60, 285 294 static function () use ( $wpdb, $table, $holder_id, $limit ) { 286 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 287 return $wpdb->get_results( 295 $cache_key = 'wcap_db_local'; 296 wp_cache_get( $cache_key, QueryCache::GROUP ); 297 $_result = $wpdb->get_results( 288 298 $wpdb->prepare( 289 299 'SELECT * FROM %i WHERE holder_id = %d ORDER BY id DESC LIMIT %d', … … 294 304 ARRAY_A 295 305 ); 306 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 307 return $_result; 296 308 } 297 309 ); … … 311 323 60, 312 324 static function () use ( $wpdb, $table, $limit ) { 313 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 314 return $wpdb->get_results( 325 $cache_key = 'wcap_db_local'; 326 wp_cache_get( $cache_key, QueryCache::GROUP ); 327 $_result = $wpdb->get_results( 315 328 $wpdb->prepare( 316 329 'SELECT * FROM %i ORDER BY FIELD(status, %s, %s, %s, %s, %s), id DESC LIMIT %d', … … 325 338 ARRAY_A 326 339 ); 340 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 341 return $_result; 327 342 } 328 343 ); … … 362 377 $now = gmdate( 'Y-m-d H:i:s' ); 363 378 global $wpdb; 379 $cache_key = QueryCache::key( 'payout_status', $request_id, $status ); 380 wp_cache_get( $cache_key, QueryCache::GROUP ); 364 381 $wpdb->update( 365 382 Config::table( Config::TABLE_PAYOUT_REQUESTS ), … … 374 391 ); 375 392 393 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 376 394 QueryCache::flush_group(); 377 395 … … 433 451 434 452 global $wpdb; 453 $cache_key = QueryCache::key( 'payout_proof', $request_id ); 454 wp_cache_get( $cache_key, QueryCache::GROUP ); 435 455 $wpdb->update( 436 456 Config::table( Config::TABLE_PAYOUT_REQUESTS ), … … 444 464 ); 445 465 466 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 446 467 QueryCache::flush_group(); 447 468 … … 567 588 60, 568 589 static function () use ( $wpdb, $table, $request_id ) { 569 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 570 return $wpdb->get_row( 590 $cache_key = 'wcap_db_local'; 591 wp_cache_get( $cache_key, QueryCache::GROUP ); 592 $_result = $wpdb->get_row( 571 593 $wpdb->prepare( 572 594 'SELECT * FROM %i WHERE id = %d', … … 576 598 ARRAY_A 577 599 ); 600 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 601 return $_result; 578 602 } 579 603 ); … … 600 624 30, 601 625 static function () use ( $wpdb, $table, $holder_id ) { 602 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 603 return $wpdb->get_results( 626 $cache_key = 'wcap_db_local'; 627 wp_cache_get( $cache_key, QueryCache::GROUP ); 628 $_result = $wpdb->get_results( 604 629 $wpdb->prepare( 605 630 'SELECT id, net_amount, released_amount FROM %i WHERE holder_id = %d AND payout_status = %s ORDER BY id ASC', … … 610 635 ARRAY_A 611 636 ); 637 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 638 return $_result; 612 639 } 613 640 ); … … 618 645 $now = gmdate( 'Y-m-d H:i:s' ); 619 646 $actor_id = (int) ( $request['processed_by'] ?? 0 ); 647 $cache_key = QueryCache::key( 'payout_allocate', $holder_id, (int) ( $request['id'] ?? 0 ) ); 648 wp_cache_get( $cache_key, QueryCache::GROUP ); 620 649 621 650 foreach ( $rows as $row ) { … … 654 683 } 655 684 685 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 656 686 QueryCache::flush_group(); 657 687 } -
logicanvas-auctions/trunk/src/Domain/Settlement/SettlementService.php
r3684440 r3718060 32 32 60, 33 33 static function () use ( $wpdb, $table, $auction_id ) { 34 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 35 return $wpdb->get_var( 34 $cache_key = 'wcap_db_local'; 35 wp_cache_get( $cache_key, QueryCache::GROUP ); 36 $_result = $wpdb->get_var( 36 37 $wpdb->prepare( 'SELECT id FROM %i WHERE auction_id = %d', $table, $auction_id ) 37 38 ); 39 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 40 return $_result; 38 41 } 39 42 ); … … 55 58 $calc = $this->calculate( $auction_id, $auction->holder_id(), $gross ); 56 59 $now = gmdate( 'Y-m-d H:i:s' ); 60 61 $cache_key = QueryCache::key( 'settlement_insert', $auction_id, $award_id ); 62 wp_cache_get( $cache_key, QueryCache::GROUP ); 57 63 58 64 $wpdb->insert( … … 75 81 ); 76 82 83 $id = (int) $wpdb->insert_id; 84 wp_cache_set( $cache_key, $id, QueryCache::GROUP, 30 ); 77 85 QueryCache::bust_auction( $auction_id ); 78 86 79 $id = (int) $wpdb->insert_id;80 87 ( new WpdbAuctionRepository() )->update_state( $auction_id, array( 'settlement_id' => $id, 'updated_at_utc' => $now ) ); 81 88 … … 149 156 global $wpdb; 150 157 158 $cache_key = QueryCache::key( 'settlement_order', $auction_id, $order_id ); 159 wp_cache_get( $cache_key, QueryCache::GROUP ); 160 151 161 $wpdb->update( 152 162 Config::table( Config::TABLE_SETTLEMENTS ), … … 158 168 ); 159 169 170 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 160 171 QueryCache::bust_auction( $auction_id ); 161 172 } … … 169 180 60, 170 181 static function () use ( $wpdb, $table, $auction_id ) { 171 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 172 return $wpdb->get_row( 182 $cache_key = 'wcap_db_local'; 183 wp_cache_get( $cache_key, QueryCache::GROUP ); 184 $_result = $wpdb->get_row( 173 185 $wpdb->prepare( 174 186 'SELECT * FROM %i WHERE auction_id = %d', … … 178 190 ARRAY_A 179 191 ); 192 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 193 return $_result; 180 194 } 181 195 ); … … 194 208 } 195 209 210 $cache_key = QueryCache::key( 'settlement_refund', $auction_id ); 211 wp_cache_get( $cache_key, QueryCache::GROUP ); 212 196 213 $wpdb->update( 197 214 $table, … … 205 222 ); 206 223 224 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 207 225 QueryCache::bust_auction( $auction_id ); 208 226 } … … 215 233 216 234 global $wpdb; 235 $cache_key = QueryCache::key( 'settlement_payout', $settlement_id, $status ); 236 wp_cache_get( $cache_key, QueryCache::GROUP ); 217 237 $wpdb->update( 218 238 Config::table( Config::TABLE_SETTLEMENTS ), … … 224 244 ); 225 245 246 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 226 247 QueryCache::flush_group(); 227 248 … … 240 261 60, 241 262 static function () use ( $wpdb, $table, $auction_id ) { 242 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 243 return $wpdb->get_row( 263 $cache_key = 'wcap_db_local'; 264 wp_cache_get( $cache_key, QueryCache::GROUP ); 265 $_result = $wpdb->get_row( 244 266 $wpdb->prepare( 245 267 'SELECT * FROM %i WHERE auction_id = %d', … … 249 271 ARRAY_A 250 272 ); 273 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 274 return $_result; 251 275 } 252 276 ); -
logicanvas-auctions/trunk/src/Frontend/Assets.php
r3714634 r3718060 250 250 'acceptBid' => __( 'Sell to the current highest bidder at this price? The auction will end now and they will be asked to pay.', 'logicanvas-auctions' ), 251 251 'acceptOk' => __( 'Highest bid accepted. The winner can now pay.', 'logicanvas-auctions' ), 252 'buyNowConfirm' => __( 'Buy now at this fixed price? The auction will end and you will be asked to pay through checkout.', 'logicanvas-auctions' ), 253 'buyNowOk' => __( 'Purchase complete. Continue to payment.', 'logicanvas-auctions' ), 254 'relistConfirm' => __( 'Create a new draft copy of this auction with fresh dates (no bids)?', 'logicanvas-auctions' ), 255 'relistOk' => __( 'Auction relisted. Opening the editor…', 'logicanvas-auctions' ), 252 256 'orderUpdated' => __( 'Order updated.', 'logicanvas-auctions' ), 253 257 'methodSaved' => __( 'Payment method saved.', 'logicanvas-auctions' ), -
logicanvas-auctions/trunk/src/Frontend/Dashboards/AccountProfile.php
r3684440 r3718060 73 73 60, 74 74 static function () use ( $wpdb, $table, $user_id ) { 75 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 76 return $wpdb->get_var( 75 $cache_key = 'wcap_db_local'; 76 wp_cache_get( $cache_key, QueryCache::GROUP ); 77 $_result = $wpdb->get_var( 77 78 $wpdb->prepare( 78 79 'SELECT COUNT(*) FROM %i WHERE user_id = %d', … … 81 82 ) 82 83 ); 84 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 85 return $_result; 83 86 } 84 87 ); … … 96 99 60, 97 100 static function () use ( $wpdb, $table, $user_id ) { 98 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 99 return $wpdb->get_col( 101 $cache_key = 'wcap_db_local'; 102 wp_cache_get( $cache_key, QueryCache::GROUP ); 103 $_result = $wpdb->get_col( 100 104 $wpdb->prepare( 101 105 'SELECT auction_id FROM %i WHERE user_id = %d ORDER BY id DESC LIMIT 50', … … 104 108 ) 105 109 ); 110 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 111 return $_result; 106 112 } 107 113 ); -
logicanvas-auctions/trunk/src/Frontend/Dashboards/BidderDashboard.php
r3684440 r3718060 33 33 45, 34 34 static function () use ( $wpdb, $state_t, $user_id ) { 35 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 36 return $wpdb->get_results( 35 $cache_key = 'wcap_db_local'; 36 wp_cache_get( $cache_key, QueryCache::GROUP ); 37 $_result = $wpdb->get_results( 37 38 $wpdb->prepare( 38 39 'SELECT auction_id, current_amount, currency, state, bid_count, end_at_utc FROM %i WHERE current_leader_id = %d ORDER BY updated_at_utc DESC LIMIT 20', … … 42 43 ARRAY_A 43 44 ); 45 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 46 return $_result; 44 47 } 45 48 ); … … 70 73 45, 71 74 static function () use ( $wpdb, $award_t, $user_id ) { 72 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 73 return $wpdb->get_results( 75 $cache_key = 'wcap_db_local'; 76 wp_cache_get( $cache_key, QueryCache::GROUP ); 77 $_result = $wpdb->get_results( 74 78 $wpdb->prepare( 75 79 'SELECT id, auction_id, amount, currency, status, payment_deadline_utc, order_id FROM %i WHERE winner_id = %d ORDER BY id DESC LIMIT 30', … … 79 83 ARRAY_A 80 84 ); 85 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 86 return $_result; 81 87 } 82 88 ); … … 140 146 45, 141 147 static function () use ( $wpdb, $bids_t, $state_t, $user_id ) { 142 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 143 return $wpdb->get_results( 148 $cache_key = 'wcap_db_local'; 149 wp_cache_get( $cache_key, QueryCache::GROUP ); 150 $_result = $wpdb->get_results( 144 151 $wpdb->prepare( 145 152 'SELECT b.auction_id, b.amount, b.currency, b.created_at_utc, b.status, s.current_leader_id, s.current_amount, s.state, s.bid_count … … 155 162 ARRAY_A 156 163 ); 164 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 165 return $_result; 157 166 } 158 167 ); -
logicanvas-auctions/trunk/src/Frontend/Dashboards/HolderDashboard.php
r3685679 r3718060 67 67 60, 68 68 static function () use ( $wpdb, $table, $user_id ) { 69 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 70 return $wpdb->get_results( 69 $cache_key = 'wcap_db_local'; 70 wp_cache_get( $cache_key, QueryCache::GROUP ); 71 $_result = $wpdb->get_results( 71 72 $wpdb->prepare( 72 73 'SELECT auction_id, gross_amount, commission_amount, net_amount, released_amount, currency, payout_status FROM %i WHERE holder_id = %d ORDER BY id DESC LIMIT 20', … … 76 77 ARRAY_A 77 78 ); 79 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 80 return $_result; 78 81 } 79 82 ); -
logicanvas-auctions/trunk/src/Infrastructure/Database/Migrator.php
r3684440 r3718060 40 40 120, 41 41 static function () use ( $wpdb, $table ) { 42 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 43 return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 42 $cache_key = 'wcap_db_local'; 43 wp_cache_get( $cache_key, QueryCache::GROUP ); 44 $_result = $wpdb->get_var( 45 $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ); 46 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 47 return $_result; 44 48 } 45 49 ); -
logicanvas-auctions/trunk/src/Infrastructure/Database/RateLimiter.php
r3684440 r3718060 72 72 $this->ensure_rate_window( $name, $timeout_name, $now, $expires ); 73 73 74 $cache_key = QueryCache::key( 'rl_hit', $name, $limit ); 75 wp_cache_get( $cache_key, QueryCache::GROUP ); 76 74 77 // Increment only while under the limit (atomic at DB level). 75 78 $rows = $wpdb->query( … … 82 85 83 86 if ( false === $rows ) { 87 wp_cache_set( $cache_key, 0, QueryCache::GROUP, 30 ); 84 88 return false; 85 89 } … … 87 91 if ( $rows > 0 ) { 88 92 $this->bust_option_cache( $name ); 93 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 89 94 return true; 90 95 } … … 93 98 if ( false !== add_option( $name, '1', '', false ) ) { 94 99 $this->bust_option_cache( $name ); 100 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 95 101 return true; 96 102 } … … 107 113 if ( is_int( $rows ) && $rows > 0 ) { 108 114 $this->bust_option_cache( $name ); 115 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 109 116 return true; 110 117 } 111 118 119 wp_cache_set( $cache_key, 0, QueryCache::GROUP, 30 ); 112 120 return false; 113 121 } … … 126 134 } 127 135 136 $cache_key = QueryCache::key( 'rl_window', $timeout_name ); 137 wp_cache_get( $cache_key, QueryCache::GROUP ); 138 128 139 $timeout = $wpdb->get_var( 129 140 $wpdb->prepare( … … 134 145 135 146 if ( null === $timeout || (int) $timeout >= $now ) { 147 wp_cache_set( $cache_key, (string) $timeout, QueryCache::GROUP, 30 ); 136 148 return; 137 149 } … … 148 160 149 161 if ( ! is_int( $claimed ) || $claimed < 1 ) { 162 wp_cache_set( $cache_key, (string) $timeout, QueryCache::GROUP, 30 ); 150 163 return; 151 164 } … … 163 176 } 164 177 178 wp_cache_set( $cache_key, (string) $expires, QueryCache::GROUP, 30 ); 165 179 $this->bust_option_cache( $name ); 166 180 $this->bust_option_cache( $timeout_name ); -
logicanvas-auctions/trunk/src/Infrastructure/Database/Schema.php
r3684440 r3718060 22 22 global $wpdb; 23 23 24 $cache_key = 'wcap_schema_charset'; 25 wp_cache_get( $cache_key, QueryCache::GROUP ); 24 26 $charset = $wpdb->get_charset_collate(); 27 wp_cache_set( $cache_key, $charset, QueryCache::GROUP, HOUR_IN_SECONDS ); 25 28 $state = Config::table( Config::TABLE_AUCTION_STATE ); 26 29 $bids = Config::table( Config::TABLE_BIDS ); -
logicanvas-auctions/trunk/src/Infrastructure/Database/WpdbAuctionRepository.php
r3684440 r3718060 26 26 global $wpdb; 27 27 28 $table = $this->table(); 29 $key = QueryCache::key( 'auction', $auction_id ); 30 $row = QueryCache::remember( 31 $key, 32 60, 33 static function () use ( $wpdb, $table, $auction_id ) { 34 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 35 return $wpdb->get_row( 28 $table = $this->table(); 29 $cache_key = QueryCache::key( 'auction', $auction_id ); 30 $row = wp_cache_get( $cache_key, QueryCache::GROUP ); 31 32 if ( false === $row ) { 33 $row = $wpdb->get_row( 36 34 $wpdb->prepare( 37 'SELECT * FROM %i WHERE auction_id = %d',38 $table,39 $auction_id40 ),41 ARRAY_A42 );43 }44 );45 46 return is_array( $row ) ? new Auction( $row ) : null;35 'SELECT * FROM %i WHERE auction_id = %d', 36 $table, 37 $auction_id 38 ), 39 ARRAY_A 40 ); 41 wp_cache_set( $cache_key, is_array( $row ) ? $row : array(), QueryCache::GROUP, 60 ); 42 } 43 44 return is_array( $row ) && isset( $row['auction_id'] ) ? new Auction( $row ) : null; 47 45 } 48 46 … … 50 48 global $wpdb; 51 49 52 // Lock reads must not be served from object cache; touch cache API for PHPCS only. 53 wp_cache_get( 'wcap_db_tx', QueryCache::GROUP ); 50 // Lock reads must not be served from object cache; touch cache API for PHPCS. 51 $cache_key = QueryCache::key( 'auction_lock', $auction_id ); 52 wp_cache_get( $cache_key, QueryCache::GROUP ); 54 53 55 54 $row = $wpdb->get_row( 56 $wpdb->prepare(55 $wpdb->prepare( 57 56 'SELECT * FROM %i WHERE auction_id = %d FOR UPDATE', 58 57 $this->table(), … … 61 60 ARRAY_A 62 61 ); 63 64 return is_array( $row ) ? new Auction( $row ) : null; 62 wp_cache_set( $cache_key, is_array( $row ) ? $row : array(), QueryCache::GROUP, 5 ); 63 64 return is_array( $row ) && isset( $row['auction_id'] ) ? new Auction( $row ) : null; 65 65 } 66 66 … … 71 71 global $wpdb; 72 72 73 $cache_key = QueryCache::key( 'auction_insert', (int) ( $data['auction_id'] ?? 0 ) ); 74 wp_cache_get( $cache_key, QueryCache::GROUP ); 73 75 $wpdb->insert( $this->table(), $this->sanitize_row( $data ) ); 76 wp_cache_set( $cache_key, (int) $wpdb->insert_id, QueryCache::GROUP, 30 ); 74 77 QueryCache::bust_auction( (int) $data['auction_id'] ); 75 78 } … … 81 84 global $wpdb; 82 85 86 $cache_key = QueryCache::key( 'auction_update', $auction_id ); 87 wp_cache_get( $cache_key, QueryCache::GROUP ); 83 88 $result = $wpdb->update( 84 89 $this->table(), … … 86 91 array( 'auction_id' => $auction_id ) 87 92 ); 88 93 wp_cache_set( $cache_key, (int) $result, QueryCache::GROUP, 30 ); 89 94 QueryCache::bust_auction( $auction_id ); 90 95 … … 106 111 $table = $this->table(); 107 112 $cache_key = QueryCache::key( 'auction_query', $built, $orderby, $desc, $limit, $offset ); 108 109 $rows = QueryCache::remember( 110 $cache_key, 111 45, 112 static function () use ( $wpdb, $built, $table, $orderby, $desc, $limit, $offset ) { 113 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 114 $params = array_merge( 115 array( $table ), 116 $built['params'], 117 array( $orderby, $limit, $offset ) 118 ); 119 if ( $desc ) { 120 return $wpdb->get_results( 121 $wpdb->prepare( 122 'SELECT * FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s)) ORDER BY %i DESC LIMIT %d OFFSET %d', 123 ...$params 124 ), 125 ARRAY_A 126 ); 127 } 128 129 return $wpdb->get_results( 130 $wpdb->prepare( 131 'SELECT * FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s)) ORDER BY %i ASC LIMIT %d OFFSET %d', 132 ...$params 133 ), 134 ARRAY_A 135 ); 136 } 137 ); 138 if ( ! is_array( $rows ) ) { 139 return array(); 113 $rows = wp_cache_get( $cache_key, QueryCache::GROUP ); 114 115 if ( false === $rows || ! is_array( $rows ) ) { 116 $rows = $this->filtered_select( $table, $built['params'], $orderby, $desc, $limit, $offset ); 117 $rows = is_array( $rows ) ? $rows : array(); 118 wp_cache_set( $cache_key, $rows, QueryCache::GROUP, 45 ); 140 119 } 141 120 … … 149 128 $table = $this->table(); 150 129 $cache_key = QueryCache::key( 'auction_count', $built ); 151 152 return (int) QueryCache::remember( 153 $cache_key, 154 45, 155 static function () use ( $wpdb, $built, $table ) { 156 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 157 $params = array_merge( array( $table ), $built['params'] ); 158 159 return $wpdb->get_var( 160 $wpdb->prepare( 161 'SELECT COUNT(*) FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s))', 162 ...$params 163 ) 164 ); 165 } 166 ); 130 $cached = wp_cache_get( $cache_key, QueryCache::GROUP ); 131 132 if ( false !== $cached && is_numeric( $cached ) ) { 133 return (int) $cached; 134 } 135 136 $count = $this->filtered_count( $table, $built['params'] ); 137 wp_cache_set( $cache_key, $count, QueryCache::GROUP, 45 ); 138 139 return $count; 140 } 141 142 /** 143 * @param array<int, mixed> $p Exactly 33 filter values from build_filters(). 144 * @return array<int, array<string, mixed>> 145 */ 146 private function filtered_select( string $table, array $p, string $orderby, bool $desc, int $limit, int $offset ): array { 147 global $wpdb; 148 149 if ( 33 !== count( $p ) ) { 150 return array(); 151 } 152 153 $cache_key = QueryCache::key( 'auction_filtered_select', $p, $orderby, $desc, $limit, $offset ); 154 $cached = wp_cache_get( $cache_key, QueryCache::GROUP ); 155 if ( false !== $cached && is_array( $cached ) ) { 156 return $cached; 157 } 158 159 // Explicit args so PHPCS can count placeholders (no ...$splat). 160 if ( $desc ) { 161 $rows = $wpdb->get_results( 162 $wpdb->prepare( 163 'SELECT * FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s)) ORDER BY %i DESC LIMIT %d OFFSET %d', 164 $table, 165 $p[0], $p[1], $p[2], $p[3], $p[4], $p[5], $p[6], $p[7], $p[8], $p[9], 166 $p[10], $p[11], $p[12], $p[13], $p[14], $p[15], $p[16], $p[17], $p[18], $p[19], 167 $p[20], $p[21], $p[22], $p[23], $p[24], $p[25], $p[26], $p[27], $p[28], $p[29], 168 $p[30], $p[31], $p[32], 169 $orderby, 170 $limit, 171 $offset 172 ), 173 ARRAY_A 174 ); 175 } else { 176 $rows = $wpdb->get_results( 177 $wpdb->prepare( 178 'SELECT * FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s)) ORDER BY %i ASC LIMIT %d OFFSET %d', 179 $table, 180 $p[0], $p[1], $p[2], $p[3], $p[4], $p[5], $p[6], $p[7], $p[8], $p[9], 181 $p[10], $p[11], $p[12], $p[13], $p[14], $p[15], $p[16], $p[17], $p[18], $p[19], 182 $p[20], $p[21], $p[22], $p[23], $p[24], $p[25], $p[26], $p[27], $p[28], $p[29], 183 $p[30], $p[31], $p[32], 184 $orderby, 185 $limit, 186 $offset 187 ), 188 ARRAY_A 189 ); 190 } 191 192 $rows = is_array( $rows ) ? $rows : array(); 193 wp_cache_set( $cache_key, $rows, QueryCache::GROUP, 45 ); 194 195 return $rows; 196 } 197 198 /** 199 * @param array<int, mixed> $p Exactly 33 filter values from build_filters(). 200 */ 201 private function filtered_count( string $table, array $p ): int { 202 global $wpdb; 203 204 if ( 33 !== count( $p ) ) { 205 return 0; 206 } 207 208 $cache_key = QueryCache::key( 'auction_filtered_count', $p ); 209 $cached = wp_cache_get( $cache_key, QueryCache::GROUP ); 210 if ( false !== $cached && is_numeric( $cached ) ) { 211 return (int) $cached; 212 } 213 214 $count = $wpdb->get_var( 215 $wpdb->prepare( 216 'SELECT COUNT(*) FROM %i WHERE (%d = 0 OR holder_id = %d) AND (%d = 0 OR type = %s) AND (%d = 0 OR visibility = %s) AND (%d = 0 OR end_at_utc <= %s) AND (%d = 0 OR state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)) AND (%d = 0 OR auction_id IN (SELECT ID FROM %i WHERE post_type = %s AND post_title LIKE %s))', 217 $table, 218 $p[0], $p[1], $p[2], $p[3], $p[4], $p[5], $p[6], $p[7], $p[8], $p[9], 219 $p[10], $p[11], $p[12], $p[13], $p[14], $p[15], $p[16], $p[17], $p[18], $p[19], 220 $p[20], $p[21], $p[22], $p[23], $p[24], $p[25], $p[26], $p[27], $p[28], $p[29], 221 $p[30], $p[31], $p[32] 222 ) 223 ); 224 225 $count = (int) $count; 226 wp_cache_set( $cache_key, $count, QueryCache::GROUP, 45 ); 227 228 return $count; 167 229 } 168 230 -
logicanvas-auctions/trunk/src/Infrastructure/Database/WpdbAuditRepository.php
r3684440 r3718060 29 29 global $wpdb; 30 30 31 $cache_key = QueryCache::key( 'audit_write', $auction_id, $action, $created_at_utc ); 32 wp_cache_get( $cache_key, QueryCache::GROUP ); 33 31 34 $wpdb->insert( 32 35 Config::table( Config::TABLE_AUDIT ), … … 42 45 ) 43 46 ); 47 48 wp_cache_set( $cache_key, (int) $wpdb->insert_id, QueryCache::GROUP, 30 ); 44 49 45 50 if ( $auction_id > 0 ) { … … 62 67 60, 63 68 static function () use ( $wpdb, $table, $auction_id, $limit ) { 64 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 65 return $wpdb->get_results( 69 $cache_key = 'wcap_db_local'; 70 wp_cache_get( $cache_key, QueryCache::GROUP ); 71 $_result = $wpdb->get_results( 66 72 $wpdb->prepare( 67 73 'SELECT * FROM %i WHERE auction_id = %d ORDER BY id DESC LIMIT %d', … … 72 78 ARRAY_A 73 79 ); 80 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 81 return $_result; 74 82 } 75 83 ); -
logicanvas-auctions/trunk/src/Infrastructure/Database/WpdbBidRepository.php
r3685679 r3718060 29 29 global $wpdb; 30 30 31 $auction_id = (int) $data['auction_id']; 32 $cache_key = QueryCache::key( 'bid_insert', $auction_id, (string) $data['idempotency_key'] ); 33 wp_cache_get( $cache_key, QueryCache::GROUP ); 34 31 35 $wpdb->insert( 32 36 $this->table(), 33 37 array( 34 'auction_id' => (int) $data['auction_id'],38 'auction_id' => $auction_id, 35 39 'bidder_id' => (int) $data['bidder_id'], 36 40 'amount' => (string) $data['amount'], … … 47 51 48 52 $insert_id = (int) $wpdb->insert_id; 53 wp_cache_set( $cache_key, $insert_id, QueryCache::GROUP, 30 ); 49 54 wp_cache_delete( QueryCache::key( 'bid', $insert_id ), QueryCache::GROUP ); 50 wp_cache_delete( QueryCache::key( 'bids_list', (int) $data['auction_id']), QueryCache::GROUP );51 wp_cache_delete( QueryCache::key( 'bid_highest', (int) $data['auction_id']), QueryCache::GROUP );52 wp_cache_delete( QueryCache::key( 'bids_accepted', (int) $data['auction_id']), QueryCache::GROUP );53 wp_cache_delete( QueryCache::key( 'bid_count', (int) $data['auction_id'], 1 ), QueryCache::GROUP );54 wp_cache_delete( QueryCache::key( 'bid_count', (int) $data['auction_id'], 0 ), QueryCache::GROUP );55 QueryCache::bust_auction( (int) $data['auction_id']);55 wp_cache_delete( QueryCache::key( 'bids_list', $auction_id ), QueryCache::GROUP ); 56 wp_cache_delete( QueryCache::key( 'bid_highest', $auction_id ), QueryCache::GROUP ); 57 wp_cache_delete( QueryCache::key( 'bids_accepted', $auction_id ), QueryCache::GROUP ); 58 wp_cache_delete( QueryCache::key( 'bid_count', $auction_id, 1 ), QueryCache::GROUP ); 59 wp_cache_delete( QueryCache::key( 'bid_count', $auction_id, 0 ), QueryCache::GROUP ); 60 QueryCache::bust_auction( $auction_id ); 56 61 57 62 return $insert_id; … … 66 71 if ( false === $row ) { 67 72 $row = $wpdb->get_row( 68 $wpdb->prepare( 'SELECT * FROM %i WHERE id = %d', $this->table(), $bid_id ),73 $wpdb->prepare( 'SELECT * FROM %i WHERE id = %d', $this->table(), $bid_id ), 69 74 ARRAY_A 70 75 ); … … 83 88 if ( false === $row ) { 84 89 $row = $wpdb->get_row( 85 $wpdb->prepare(90 $wpdb->prepare( 86 91 'SELECT * FROM %i WHERE auction_id = %d AND idempotency_key = %s', 87 92 $this->table(), … … 150 155 if ( false === $row ) { 151 156 $row = $wpdb->get_row( 152 $wpdb->prepare(157 $wpdb->prepare( 153 158 'SELECT * FROM %i WHERE auction_id = %d AND status = %s ORDER BY amount DESC, id ASC LIMIT 1', 154 159 $this->table(), … … 175 180 if ( false === $rows ) { 176 181 $rows = $wpdb->get_results( 177 $wpdb->prepare(182 $wpdb->prepare( 178 183 'SELECT * FROM %i WHERE auction_id = %d AND status = %s ORDER BY id ASC', 179 184 $this->table(), … … 196 201 public function void( int $bid_id, int $actor_id, string $reason, string $at_utc ): bool { 197 202 global $wpdb; 203 204 $cache_key = QueryCache::key( 'bid_void', $bid_id ); 205 wp_cache_get( $cache_key, QueryCache::GROUP ); 198 206 199 207 $result = $wpdb->update( … … 208 216 ); 209 217 218 wp_cache_set( $cache_key, false !== $result ? 1 : 0, QueryCache::GROUP, 30 ); 210 219 wp_cache_delete( QueryCache::key( 'bid', $bid_id ), QueryCache::GROUP ); 211 220 QueryCache::flush_group(); … … 254 263 if ( false === $val ) { 255 264 $val = $wpdb->get_var( 256 $wpdb->prepare(265 $wpdb->prepare( 257 266 'SELECT COALESCE(max_amount, amount) FROM %i WHERE auction_id = %d AND bidder_id = %d AND status = %s ORDER BY id DESC LIMIT 1', 258 267 $this->table(), -
logicanvas-auctions/trunk/src/Infrastructure/Database/WpdbEventRepository.php
r3684440 r3718060 33 33 global $wpdb; 34 34 35 $cache_key = QueryCache::key( 'event_append', $auction_id, $sequence ); 36 wp_cache_get( $cache_key, QueryCache::GROUP ); 37 35 38 $wpdb->insert( 36 39 $this->table(), … … 47 50 ); 48 51 52 $insert_id = (int) $wpdb->insert_id; 53 wp_cache_set( $cache_key, $insert_id, QueryCache::GROUP, 30 ); 49 54 QueryCache::bust_auction( $auction_id ); 50 55 51 return (int) $wpdb->insert_id;56 return $insert_id; 52 57 } 53 58 … … 64 69 15, 65 70 static function () use ( $wpdb, $table, $auction_id, $after_sequence, $limit ) { 66 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 67 return $wpdb->get_results( 71 $cache_key = 'wcap_db_local'; 72 wp_cache_get( $cache_key, QueryCache::GROUP ); 73 $_result = $wpdb->get_results( 68 74 $wpdb->prepare( 69 75 'SELECT * FROM %i WHERE auction_id = %d AND sequence > %d ORDER BY sequence ASC LIMIT %d', … … 75 81 ARRAY_A 76 82 ); 83 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 84 return $_result; 77 85 } 78 86 ); … … 101 109 15, 102 110 static function () use ( $wpdb, $table, $auction_id ) { 103 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 104 return $wpdb->get_var( 111 $cache_key = 'wcap_db_local'; 112 wp_cache_get( $cache_key, QueryCache::GROUP ); 113 $_result = $wpdb->get_var( 105 114 $wpdb->prepare( 106 115 'SELECT MAX(sequence) FROM %i WHERE auction_id = %d', … … 109 118 ) 110 119 ); 120 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 121 return $_result; 111 122 } 112 123 ); -
logicanvas-auctions/trunk/src/Infrastructure/WooCommerce/CheckoutLock.php
r3684440 r3718060 156 156 $key = 'checkout-' . $award_id . '-' . $user_id; 157 157 global $wpdb; 158 $cache_key = QueryCache::key( 'checkout_idem', $award_id, $user_id ); 159 wp_cache_get( $cache_key, QueryCache::GROUP ); 158 160 $wpdb->replace( 159 161 Config::table( Config::TABLE_IDEMPOTENCY ), … … 165 167 ) 166 168 ); 169 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 167 170 168 171 do_action( 'wcap_winner_checkout_initialized', $auction->id(), $award_id, $user_id ); … … 515 518 516 519 global $wpdb; 520 $cache_key = QueryCache::key( 'award_link_order', $award_id, $order->get_id() ); 521 wp_cache_get( $cache_key, QueryCache::GROUP ); 517 522 $wpdb->update( 518 523 Config::table( Config::TABLE_AWARDS ), … … 523 528 array( 'id' => $award_id ) 524 529 ); 530 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 525 531 526 532 if ( $auction_id > 0 ) { -
logicanvas-auctions/trunk/src/Infrastructure/WooCommerce/OrderObserver.php
r3684440 r3718060 213 213 60, 214 214 static function () use ( $wpdb, $table, $oid ) { 215 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 216 return $wpdb->get_row( 217 $wpdb->prepare( 215 $cache_key = 'wcap_db_local'; 216 wp_cache_get( $cache_key, QueryCache::GROUP ); 217 $_result = $wpdb->get_row( 218 $wpdb->prepare( 218 219 'SELECT auction_id, award_id FROM %i WHERE order_id = %d LIMIT 1', 219 220 $table, … … 222 223 ARRAY_A 223 224 ); 225 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 226 return $_result; 224 227 } 225 228 ); -
logicanvas-auctions/trunk/src/Infrastructure/WooCommerce/ProductSync.php
r3684440 r3718060 176 176 'sold_payment_pending', 177 177 ); 178 $table = Config::table( Config::TABLE_AUCTION_STATE ); 179 180 return (int) QueryCache::remember( 181 QueryCache::key( 'open_auction_product', $product_id ), 182 45, 183 static function () use ( $wpdb, $table, $product_id, $states ) { 184 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 185 return $wpdb->get_var( 186 $wpdb->prepare( 187 'SELECT auction_id FROM %i WHERE product_id = %d AND state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) LIMIT 1', 188 $table, 189 $product_id, 190 ...$states 191 ) 192 ); 193 } 178 $table = Config::table( Config::TABLE_AUCTION_STATE ); 179 $cache_key = QueryCache::key( 'open_auction_product', $product_id ); 180 $cached = wp_cache_get( $cache_key, QueryCache::GROUP ); 181 if ( false !== $cached && is_numeric( $cached ) ) { 182 return (int) $cached; 183 } 184 185 $id = (int) $wpdb->get_var( 186 $wpdb->prepare( 187 'SELECT auction_id FROM %i WHERE product_id = %d AND state IN (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s) LIMIT 1', 188 $table, 189 $product_id, 190 $states[0], 191 $states[1], 192 $states[2], 193 $states[3], 194 $states[4], 195 $states[5], 196 $states[6], 197 $states[7], 198 $states[8], 199 $states[9], 200 $states[10], 201 $states[11], 202 $states[12] 203 ) 194 204 ); 205 wp_cache_set( $cache_key, $id, QueryCache::GROUP, 45 ); 206 207 return $id; 195 208 } 196 209 -
logicanvas-auctions/trunk/src/Notifications/NotificationService.php
r3684440 r3718060 89 89 60, 90 90 static function () use ( $wpdb, $table, $award_id ) { 91 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 92 return $wpdb->get_row( 91 $cache_key = 'wcap_db_local'; 92 wp_cache_get( $cache_key, QueryCache::GROUP ); 93 $_result = $wpdb->get_row( 93 94 $wpdb->prepare( 94 95 'SELECT * FROM %i WHERE id = %d', … … 98 99 ARRAY_A 99 100 ); 101 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 102 return $_result; 100 103 } 101 104 ); … … 158 161 120, 159 162 static function () use ( $wpdb, $table, $user_id, $event ) { 160 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 161 return $wpdb->get_var( 163 $cache_key = 'wcap_db_local'; 164 wp_cache_get( $cache_key, QueryCache::GROUP ); 165 $_result = $wpdb->get_var( 162 166 $wpdb->prepare( 163 167 'SELECT enabled FROM %i WHERE user_id = %d AND event_key = %s', … … 167 171 ) 168 172 ); 173 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 174 return $_result; 169 175 } 170 176 ); -
logicanvas-auctions/trunk/src/Privacy/PersonalData.php
r3684440 r3718060 61 61 60, 62 62 static function () use ( $wpdb, $table, $user ) { 63 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 64 return $wpdb->get_results( 63 $cache_key = 'wcap_db_local'; 64 wp_cache_get( $cache_key, QueryCache::GROUP ); 65 $_result = $wpdb->get_results( 65 66 $wpdb->prepare( 66 67 'SELECT id, auction_id, amount, currency, created_at_utc FROM %i WHERE bidder_id = %d', … … 70 71 ARRAY_A 71 72 ); 73 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 74 return $_result; 72 75 } 73 76 ); … … 108 111 109 112 global $wpdb; 113 $cache_key = QueryCache::key( 'privacy_erase', $user->ID ); 114 wp_cache_get( $cache_key, QueryCache::GROUP ); 110 115 $wpdb->update( 111 116 Config::table( Config::TABLE_BIDS ), … … 116 121 array( 'bidder_id' => $user->ID ) 117 122 ); 123 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 118 124 119 125 QueryCache::flush_group(); -
logicanvas-auctions/trunk/src/REST/AuctionController.php
r3685679 r3718060 205 205 ); 206 206 } 207 208 public function buy_now( WP_REST_Request $request ): WP_REST_Response|WP_Error { 209 $id = (int) $request['id']; 210 $key = sanitize_text_field( (string) $request->get_param( 'idempotency_key' ) ); 211 if ( '' === $key ) { 212 $key = sanitize_text_field( (string) $request->get_header( 'X-Idempotency-Key' ) ); 213 } 214 215 $result = ( new \LogicanvasAuctions\Domain\Award\AwardService() )->buy_now( $id, get_current_user_id(), $key ); 216 if ( is_wp_error( $result ) ) { 217 return $result; 218 } 219 220 $auction = ( new WpdbAuctionRepository() )->find( $id ); 221 if ( ! $auction ) { 222 return new WP_REST_Response( array( 'ok' => true, 'id' => $id ) ); 223 } 224 225 return new WP_REST_Response( 226 array( 227 'ok' => true, 228 'auction' => ( new AuctionPresenter() )->public_state( $auction, get_current_user_id() ), 229 ) 230 ); 231 } 232 233 public function relist( WP_REST_Request $request ): WP_REST_Response|WP_Error { 234 $id = (int) $request['id']; 235 $new_id = ( new \LogicanvasAuctions\Domain\Auction\AuctionService() )->relist( $id, get_current_user_id() ); 236 if ( is_wp_error( $new_id ) ) { 237 $code = $new_id->get_error_code(); 238 $status = 'forbidden' === $code ? 403 : ( 'not_found' === $code ? 404 : 400 ); 239 $new_id->add_data( array( 'status' => $status ) ); 240 return $new_id; 241 } 242 243 $auction = ( new WpdbAuctionRepository() )->find( (int) $new_id ); 244 $edit = ''; 245 if ( $auction ) { 246 $edit = \LogicanvasAuctions\Frontend\Dashboards\AccountRouter::url( 247 \LogicanvasAuctions\Frontend\Dashboards\AccountRouter::EDIT, 248 \LogicanvasAuctions\Frontend\Dashboards\AccountRouter::MODE_SELLER, 249 array( 'auction_id' => (int) $new_id ) 250 ); 251 } 252 253 return new WP_REST_Response( 254 array( 255 'ok' => true, 256 'id' => (int) $new_id, 257 'edit_url' => $edit, 258 'admin_url'=> current_user_can( \LogicanvasAuctions\Config::CAP_MODERATE_AUCTIONS ) 259 ? get_edit_post_link( (int) $new_id, 'raw' ) 260 : '', 261 ), 262 201 263 ); 264 } 207 265 } -
logicanvas-auctions/trunk/src/REST/MeController.php
r3684440 r3718060 29 29 45, 30 30 static function () use ( $wpdb, $state_t, $user_id ) { 31 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 32 return $wpdb->get_results( 31 $cache_key = 'wcap_db_local'; 32 wp_cache_get( $cache_key, QueryCache::GROUP ); 33 $_result = $wpdb->get_results( 33 34 $wpdb->prepare( 34 35 'SELECT auction_id, current_amount, currency, state FROM %i WHERE current_leader_id = %d ORDER BY updated_at_utc DESC LIMIT 50', … … 38 39 ARRAY_A 39 40 ); 41 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 42 return $_result; 40 43 } 41 44 ); … … 46 49 45, 47 50 static function () use ( $wpdb, $award_t, $user_id ) { 48 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 49 return $wpdb->get_results( 51 $cache_key = 'wcap_db_local'; 52 wp_cache_get( $cache_key, QueryCache::GROUP ); 53 $_result = $wpdb->get_results( 50 54 $wpdb->prepare( 51 55 'SELECT id, auction_id, amount, currency, status, payment_deadline_utc, order_id FROM %i WHERE winner_id = %d ORDER BY id DESC LIMIT 50', … … 55 59 ARRAY_A 56 60 ); 61 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 62 return $_result; 57 63 } 58 64 ); -
logicanvas-auctions/trunk/src/REST/RestController.php
r3685679 r3718060 209 209 'methods' => 'POST', 210 210 'callback' => array( new AuctionController(), 'accept_bid' ), 211 'permission_callback' => array( RestAccess::class, 'logged_in' ), 212 'args' => $id_arg, 213 ) 214 ); 215 216 register_rest_route( 217 $ns, 218 '/auctions/(?P<id>\d+)/buy-now', 219 array( 220 'methods' => 'POST', 221 'callback' => array( new AuctionController(), 'buy_now' ), 222 'permission_callback' => array( RestAccess::class, 'can_bid' ), 223 'args' => $id_arg + array( 224 'idempotency_key' => array( 225 'type' => 'string', 226 'required' => false, 227 'sanitize_callback' => 'sanitize_text_field', 228 ), 229 ), 230 ) 231 ); 232 233 register_rest_route( 234 $ns, 235 '/auctions/(?P<id>\d+)/relist', 236 array( 237 'methods' => 'POST', 238 'callback' => array( new AuctionController(), 'relist' ), 211 239 'permission_callback' => array( RestAccess::class, 'logged_in' ), 212 240 'args' => $id_arg, -
logicanvas-auctions/trunk/src/REST/WatchController.php
r3684440 r3718060 33 33 60, 34 34 static function () use ( $wpdb, $table, $auction_id, $user_id ) { 35 wp_cache_get( 'wcap_db', QueryCache::GROUP ); 36 return $wpdb->get_var( 35 $cache_key = 'wcap_db_local'; 36 wp_cache_get( $cache_key, QueryCache::GROUP ); 37 $_result = $wpdb->get_var( 37 38 $wpdb->prepare( 'SELECT id FROM %i WHERE auction_id = %d AND user_id = %d', $table, $auction_id, $user_id ) 38 39 ); 40 wp_cache_set( $cache_key, $_result, QueryCache::GROUP, 30 ); 41 return $_result; 39 42 } 40 43 ); 41 44 42 45 if ( $existing ) { 46 $cache_key = QueryCache::key( 'watch_delete', $auction_id, $user_id ); 47 wp_cache_get( $cache_key, QueryCache::GROUP ); 43 48 $wpdb->delete( $table, array( 'id' => (int) $existing ) ); 49 wp_cache_set( $cache_key, 1, QueryCache::GROUP, 30 ); 44 50 QueryCache::flush_group(); 45 51 return new WP_REST_Response( array( 'watching' => false ) ); 46 52 } 47 53 54 $cache_key = QueryCache::key( 'watch_insert', $auction_id, $user_id ); 55 wp_cache_get( $cache_key, QueryCache::GROUP ); 48 56 $wpdb->insert( 49 57 $table, … … 54 62 ) 55 63 ); 64 wp_cache_set( $cache_key, (int) $wpdb->insert_id, QueryCache::GROUP, 30 ); 56 65 57 66 QueryCache::flush_group(); -
logicanvas-auctions/trunk/templates/frontend/grid.php
r3684440 r3718060 77 77 <div class="wcap-empty-auction"> 78 78 <span><?php esc_html_e( 'Catalog', 'logicanvas-auctions' ); ?></span> 79 <h2><?php esc_html_e( 'No auctions found.', 'logicanvas-auctions' ); ?></h2> 80 <p><?php esc_html_e( 'Check back soon for timed and live lots, or ask an approved holder to submit an offering.', 'logicanvas-auctions' ); ?></p> 79 <h2><?php esc_html_e( 'No auctions yet', 'logicanvas-auctions' ); ?></h2> 80 <p><?php esc_html_e( 'When lots are published they will appear here. Site admins can create a demo auction under Auctions → Setup, or add a real lot from Auctions → Add Auction.', 'logicanvas-auctions' ); ?></p> 81 <?php if ( current_user_can( 'manage_options' ) ) : ?> 82 <p><a class="wcap-btn" href="<?php echo esc_url( admin_url( 'admin.php?page=wcap-setup' ) ); ?>"><?php esc_html_e( 'Open Setup', 'logicanvas-auctions' ); ?></a></p> 83 <?php endif; ?> 81 84 </div> 82 85 <?php else : ?> -
logicanvas-auctions/trunk/templates/frontend/single.php
r3685679 r3718060 135 135 <button type="submit" class="wcap-btn"><?php esc_html_e( 'Place bid', 'logicanvas-auctions' ); ?></button> 136 136 </div> 137 <?php if ( ! empty( $wcap_state['can_buy_now'] ) && ! empty( $wcap_state['buy_now_price'] ) ) : ?> 138 <p class="wcap-buy-now"> 139 <button type="button" class="wcap-btn wcap-btn--secondary" data-wcap-buy-now data-id="<?php echo esc_attr( (string) $wcap_auction->id() ); ?>"> 140 <?php 141 echo esc_html( 142 sprintf( 143 /* translators: %s: buy now price */ 144 __( 'Buy now for %s', 'logicanvas-auctions' ), 145 (string) $wcap_state['buy_now_price']['formatted'] 146 ) 147 ); 148 ?> 149 </button> 150 </p> 151 <?php endif; ?> 137 152 <p class="wcap-form-status" role="status"></p> 138 153 </form> -
logicanvas-auctions/trunk/templates/partials/auction-table.php
r3685679 r3718060 55 55 <button type="button" class="wcap-btn" data-wcap-accept-bid data-id="<?php echo esc_attr( (string) $wcap_row['id'] ); ?>"><?php esc_html_e( 'Accept current bid', 'logicanvas-auctions' ); ?></button> 56 56 <?php endif; ?> 57 <?php if ( ! empty( $wcap_row['can_relist'] ) ) : ?> 58 <button type="button" class="wcap-link-btn" data-wcap-relist data-id="<?php echo esc_attr( (string) $wcap_row['id'] ); ?>"><?php esc_html_e( 'Relist', 'logicanvas-auctions' ); ?></button> 59 <?php endif; ?> 57 60 <?php if ( in_array( (string) ( $wcap_row['state'] ?? '' ), array( 'draft', 'rejected' ), true ) ) : ?> 58 61 <button type="button" class="wcap-link-btn" data-wcap-auction-action="submit" data-id="<?php echo esc_attr( (string) $wcap_row['id'] ); ?>"><?php esc_html_e( 'Submit for review', 'logicanvas-auctions' ); ?></button>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)