turnstile

Drupal paywall plugin
Log | Files | Refs | README | LICENSE

commit 0db0f25e26770ca8ce23a0197d0c5de3994e2956
parent 33783730a7758ccfd905400ac704f5d154f96183
Author: Christian Grothoff <christian@grothoff.org>
Date:   Fri,  3 Oct 2025 17:35:44 +0200

printf-debug fest

Diffstat:
Mturnstile.module | 32+++++++++++++++++++++++++++++++-
1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/turnstile.module b/turnstile.module @@ -51,11 +51,13 @@ function turnstile_entity_bundle_field_info_alter(&$fields, EntityTypeInterface function turnstile_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) { // Only process nodes. if (!$entity instanceof NodeInterface) { + \Drupal::logger('turnstile')->debug('Not a node, skipping Turnstile checks.'); return; } // Check if the node has a price field and it's not empty. if (!$entity->hasField('field_price') || $entity->get('field_price')->isEmpty()) { + \Drupal::logger('turnstile')->debug('Node has no price, skipping Turnstile checks.'); return; } @@ -65,25 +67,34 @@ function turnstile_entity_view_alter(array &$build, EntityInterface $entity, Ent // Check if this node type is enabled for paywall. if (!in_array($entity->bundle(), $enabled_types)) { + \Drupal::logger('turnstile')->debug('Bundle not enabled with Turnstile, skipping payment.'); return; } // Get the original body content. if (!$entity->hasField('body')) { + \Drupal::logger('turnstile')->debug('Note has no body, skipping payment.'); return; } if ($entity->get('body')->isEmpty()) { + \Drupal::logger('turnstile')->debug('Note has empty body, skipping payment.'); return; } $body_value = $entity->get('body')->value; // Call the paywall check function with the node. + \Drupal::logger('turnstile')->debug('Checking for payment...'); $transformed_body = turnstile_check_paywall_cookie($body_value, $entity); // Update the body in the build array. if (isset($build['body'][0]['#text'])) { + \Drupal::logger('turnstile')->debug('Transformed body for Turnstile.'); $build['body'][0]['#text'] = $transformed_body; } + else + { + \Drupal::logger('turnstile')->debug('Failed to inject transformed body.'); + } } @@ -107,6 +118,7 @@ function turnstile_check_paywall_cookie($body, NodeInterface $node) { // Check if user is a subscriber. if (isset($_SESSION['turnstile_subscriber']) && $_SESSION['turnstile_subscriber'] === TRUE) { + \Drupal::logger('turnstile')->debug('Subscriber cookie detected, passing turnstile'); // FIXME: should set turnstile_subscriber to *expiration* time // of the subscription and check not for TRUE but for "greater // current time". @@ -118,6 +130,7 @@ function turnstile_check_paywall_cookie($body, NodeInterface $node) { $node_id = $node ? $node->id() : NULL; if (!$node_id) { // Strange, but not a case where we can do a payment. + \Drupal::logger('turnstile')->debug('No payment due to lack of node ID...'); return $body; } @@ -129,16 +142,19 @@ function turnstile_check_paywall_cookie($body, NodeInterface $node) { // keep support for them here? if (isset($order['paid']) && $order['paid'] === TRUE && (!isset($order['refunded']) || $order['refunded'] === FALSE)) { + \Drupal::logger('turnstile')->debug('Paid order detected, passing Turnstile.'); return $body; } // Check order status with backend if not marked as paid. if (!$order['paid']) { + \Drupal::logger('turnstile')->debug('Checking order status ...'); $status = turnstile_check_order_status($order['order_id']); if ($status && $status['paid']) { // Update session with new status. // FIXME: if we keep refunds above, we should check // for refunds here as well! + \Drupal::logger('turnstile')->debug('Updating order status to paid.'); $_SESSION['turnstile_orders'][$node_id]['paid'] = TRUE; return $body; } @@ -148,6 +164,7 @@ function turnstile_check_paywall_cookie($body, NodeInterface $node) { // No valid payment found, need to create order or show payment option. $order_info = turnstile_create_or_get_order($node); if (! $order_info) { + \Drupal::logger('turnstile')->debug('Failed to create order.'); // Fallback: just return body, not good to have unhappy readers. $config = \Drupal::config('turnstile.settings'); $grant_access_on_error = $config->get('grant_access_on_error') ?: true; @@ -157,6 +174,7 @@ function turnstile_check_paywall_cookie($body, NodeInterface $node) { return 'Error: failed to setup order with payment backend'; } + \Drupal::logger('turnstile')->debug('Rendering page with payment request.'); return turnstile_render_preview_with_payment_button($body, $order_info); } @@ -176,6 +194,7 @@ function turnstile_create_or_get_order(NodeInterface $node) { // Check if we already have an order for this node in session if (isset($_SESSION['turnstile_orders'][$node_id])) { // FIXME: check of order expired, not useful if payment deadline expired! + \Drupal::logger('turnstile')->debug('Re-using existing order.'); return $_SESSION['turnstile_orders'][$node_id]; } @@ -184,9 +203,10 @@ function turnstile_create_or_get_order(NodeInterface $node) { if ($order_info) { // Store order in session $_SESSION['turnstile_orders'][$node_id] = $order_info; + \Drupal::logger('turnstile')->debug('Created new order.'); return $order_info; } - + \Drupal::logger('turnstile')->debug('Failed to create order.'); return FALSE; } @@ -207,6 +227,7 @@ function turnstile_truncate_content_safely($content, $length = 200) { $text_only = strip_tags($content); if (strlen($text_only) <= $length) { + \Drupal::logger('turnstile')->debug('Body too short, skipping payment transformation.'); return $content; } @@ -244,6 +265,7 @@ function turnstile_truncate_content_safely($content, $length = 200) { $current_length += strlen($node_text); } } + \Drupal::logger('turnstile')->debug('Returning truncated body.'); return $truncated; } @@ -263,6 +285,7 @@ function turnstile_truncate_content_safely($content, $length = 200) { function turnstile_render_preview_with_payment_button($body, $order_info) { // Safely truncate content to first few lines. $preview = turnstile_truncate_content_safely($body, 200); + \Drupal::logger('turnstile')->debug('Generating payment request body'); // FIXME: eventually, we may want to at least give the option to // inline the payment dialog / QR code and long-poll ourselves, @@ -309,6 +332,7 @@ function turnstile_check_order_status($order_id) { $access_token = $config->get('access_token'); if (empty($backend_url) || empty($access_token)) { + \Drupal::logger('turnstile')->debug('No backend, cannot check order status'); return FALSE; } @@ -322,6 +346,8 @@ function turnstile_check_order_status($order_id) { // Check HTTP status if ($response->getStatusCode() !== 200) { + // FIXME: treat expired/deleted orders differently! + \Drupal::logger('turnstile')->debug('Failed to obtain order status'); return FALSE; } @@ -361,11 +387,13 @@ function turnstile_create_order(NodeInterface $node) { $access_token = $config->get('access_token'); if (empty($backend_url) || empty($access_token)) { + \Drupal::logger('turnstile')->debug('No backend, cannot setup new order'); return FALSE; } $price = $node->get('field_price')->value; if (empty($price)) { + \Drupal::logger('turnstile')->debug('No price, cannot setup new order'); return FALSE; } @@ -392,6 +420,7 @@ function turnstile_create_order(NodeInterface $node) { // Check HTTP status if ($response->getStatusCode() !== 200 && $response->getStatusCode() !== 201) { + \Drupal::logger('turnstile')->debug('Backend failed to setup new order'); return FALSE; } @@ -406,6 +435,7 @@ function turnstile_create_order(NodeInterface $node) { 'created' => time(), // FIXME: probably better keep when offer expires! ]; } + \Drupal::logger('turnstile')->debug('Unexpected error trying to setup new order: no order_id returned'); } catch (RequestException $e) { \Drupal::logger('turnstile')->error('Failed to create Taler order: @message', ['@message' => $e->getMessage()]);