where('sSlug', config('tutorials.beginner_slug'))->where('iStatus', 1)->first(); $guide = DB::table('articles')->where('sSlug', config('tutorials.guide_slug'))->where('iStatus', 1)->first(); if (! $category || ! $guide || $guide->iCategoryId !== $category->id) { $this->error('Publish the guide in the beginner category before applying metadata.'); return self::FAILURE; } $this->line(json_encode(['category' => $category->sSlug, 'name' => config('tutorials.beginner_name'), 'guide' => $guide->sSlug, 'pinned' => true], JSON_UNESCAPED_UNICODE)); if (! $this->option('apply')) return self::SUCCESS; $backup = storage_path('app/private/editorial/tutorial-metadata-'.Str::uuid().'.json'); $snapshot = ['category_id' => $category->id, 'sName' => $category->sName, 'guide_id' => $guide->id, 'iIsTop' => $guide->iIsTop]; file_put_contents($backup, json_encode($snapshot, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)); chmod($backup, 0600); DB::transaction(function () use ($category, $guide) { $currentCategory = DB::table('categories')->where('id', $category->id)->lockForUpdate()->first(); $currentGuide = DB::table('articles')->where('id', $guide->id)->lockForUpdate()->first(); if ($currentCategory->sName !== $category->sName || $currentGuide->iCategoryId !== $category->id || ! $currentGuide->iStatus) { throw new \RuntimeException('Tutorial metadata changed; inspect before retrying.'); } DB::table('categories')->where('id', $category->id)->update(['sName' => config('tutorials.beginner_name')]); DB::table('articles')->where('id', $guide->id)->update(['iIsTop' => 1]); }); Cache::forget('global_nav_tree'); \Spatie\ResponseCache\Facades\ResponseCache::clear(); $this->info('Category renamed and guide pinned. Private backup: '.$backup); return self::SUCCESS; } }