Variable HARVEST_SHELL_PHPConst
HARVEST_SHELL_PHP: "\nuse Drupal\\Core\\Cache\\CacheableResponseInterface;\nuse Drupal\\Core\\DrupalKernel;\nuse Drupal\\Core\\Site\\Settings;\nuse Symfony\\Component\\HttpFoundation\\Request;\n\n// __CFW_FIBER_SHIM__\n// __CFW_HOST_HELPERS__\n// __CFW_PW_SERVE_INLINE__\nchdir('/drupal');\n\n$path = json_decode(__CFW_PATH__);\n$cookie = json_decode(__CFW_COOKIE__);\n$origin = json_decode(__CFW_ORIGIN__);\n$out = ['ok' => false, 'path' => $path];\n$clock = function () {\n\treturn microtime(true) * 1000;\n};\n\ntry {\n\tif (!isset($GLOBALS['__pw_autoloader']) || !is_object($GLOBALS['__pw_autoloader'])) {\n\t\t$GLOBALS['__pw_autoloader'] = require '/drupal/autoload.php';\n\t}\n\t$autoloader = $GLOBALS['__pw_autoloader'];\n\tif (!isset($GLOBALS['__pw_kernel'])) {\n\t\t$boot = Request::create('/', 'GET');\n\t\t$kernel = new DrupalKernel('prod', $autoloader);\n\t\tDrupalKernel::bootEnvironment();\n\t\t$sitePath = DrupalKernel::findSitePath($boot);\n\t\t$kernel->setSitePath($sitePath);\n\t\tSettings::initialize('/drupal', $sitePath, $autoloader);\n\t\t$kernel->boot();\n\t\t$GLOBALS['__pw_kernel'] = $kernel;\n\t}\n\n\t// the render bin is the gate on whether holes exist at all; emptying dynamic_page_cache alone\n\t// produces a MISS with the placeholders already substituted, which reads as \"no shell\"\n\tforeach (['dynamic_page_cache', 'render'] as $bin) {\n\t\ttry {\n\t\t\tDrupal::cache($bin)->deleteAll();\n\t\t} catch (Throwable $e) {\n\t\t}\n\t}\n\ttry {\n\t\t$middleware = Drupal::service('http_middleware.page_cache');\n\t\t$rp = new ReflectionProperty($middleware, 'cid');\n\t\t$rp->setValue($middleware, null);\n\t} catch (Throwable $e) {\n\t}\n\n\t$t0 = $clock();\n\t$response = cfw_serve($path, false, 'GET', '', '', $cookie, $origin, '');\n\t$out['harvestMs'] = round($clock() - $t0, 2);\n\n\t// BEFORE sendContent(), which consumes them\n\t$attachments = method_exists($response, 'getAttachments') ? $response->getAttachments() : [];\n\t$recipes = $attachments['big_pipe_placeholders'] ?? [];\n\t$out['recipes'] = $recipes;\n\t$out['recipeCount'] = count($recipes);\n\n\t$body = '';\n\tif (method_exists($response, 'sendContent')) {\n\t\t$depth = ob_get_level();\n\t\tob_start();\n\t\ttry {\n\t\t\t$response->sendContent();\n\t\t\t$body = (string) ob_get_clean();\n\t\t} catch (Throwable $e) {\n\t\t\twhile (ob_get_level() > $depth) {\n\t\t\t\t@ob_end_clean();\n\t\t\t}\n\t\t\t// same reason as the fill path: the throw skipped BigPipe's own session save\n\t\t\t$out['sendError'] = get_class($e) . ': ' . $e->getMessage();\n\t\t\t$out['sessionClosed'] = cfw_close_session();\n\t\t\t$body = (string) $response->getContent();\n\t\t}\n\t} else {\n\t\t$body = (string) $response->getContent();\n\t}\n\n\t$out['html'] = $body;\n\t$out['bytes'] = strlen($body);\n\t$out['status'] = $response->getStatusCode();\n\t$out['dynamicCache'] = $response->headers->get('x-drupal-dynamic-cache');\n\t// the cache tags this render bubbled, so a compiled plan can be invalidated by the same tags\n\t// Drupal would invalidate the render cache with\n\ttry {\n\t\t$out['cacheTags'] =\n\t\t\t$response instanceof CacheableResponseInterface\n\t\t\t\t? array_values($response->getCacheableMetadata()->getCacheTags())\n\t\t\t\t: [];\n\t} catch (Throwable $e) {\n\t\t$out['cacheTags'] = [];\n\t}\n\t$out['uid'] = (int) Drupal::currentUser()->id();\n\t$out['roles'] = array_values(Drupal::currentUser()->getRoles());\n\t$out['ok'] = true;\n} catch (Throwable $e) {\n\t$out['error'] = get_class($e) . ': ' . $e->getMessage();\n\t$out['trace'] = substr($e->getTraceAsString(), 0, 900);\n}\n\necho json_encode($out);\n"