.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use Exception;
use FireflyIII\Enums\AccountTypeEnum;
use FireflyIII\Enums\TransactionTypeEnum;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Models\PeriodStatistic;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface;
use FireflyIII\Support\Facades\Amount;
use FireflyIII\Support\Facades\FireflyConfig;
use FireflyIII\Support\Facades\Preferences;
use FireflyIII\Support\Facades\Steam;
use FireflyIII\Support\Http\Controllers\GetConfigurationData;
use FireflyIII\Support\Models\AccountBalanceCalculator;
use FireflyIII\User;
use Illuminate\Contracts\View\Factory;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
use Illuminate\View\View;
use Monolog\Handler\RotatingFileHandler;
use Safe\Exceptions\FilesystemException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use function Safe\file_get_contents;
use function Safe\ini_get;
use const PHP_INT_SIZE;
use const PHP_SAPI;
/**
* Class DebugController
*/
class DebugController extends Controller
{
use GetConfigurationData;
/**
* DebugController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(IsDemoUser::class)->except(['displayError']);
}
public function apiTest(): View
{
return view('test.api-test');
}
/**
* Show all possible errors.
*
* @throws FireflyException
*/
public function displayError(): void
{
Log::debug('This is a test message at the DEBUG level.');
Log::info('This is a test message at the INFO level.');
Log::notice('This is a test message at the NOTICE level.');
Log::warning('This is a test message at the WARNING level.');
Log::error('This is a test message at the ERROR level.');
Log::critical('This is a test message at the CRITICAL level.');
Log::alert('This is a test message at the ALERT level.');
Log::emergency('This is a test message at the EMERGENCY level.');
throw new FireflyException('A very simple test error.');
}
/**
* Clear log and session.
*
* @throws FireflyException
*/
public function flush(Request $request): Redirector|RedirectResponse
{
Preferences::mark();
$request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range', 'temp-mfa-secret', 'temp-mfa-codes']);
Artisan::call('cache:clear');
Artisan::call('config:clear');
Artisan::call('route:clear');
Artisan::call('view:clear');
PeriodStatistic::where('id', '>', 0)->delete();
// also do some recalculations.
Artisan::call('correction:recalculates-liabilities');
if (true === FireflyConfig::get('use_running_balance', config('firefly.feature_flags.running_balance_column'))->data) {
AccountBalanceCalculator::recalculateAll(false);
}
try {
Artisan::call('twig:clean');
} catch (Exception $e) { // intentional generic exception
throw new FireflyException($e->getMessage(), 0, $e);
}
Artisan::call('view:clear');
return redirect(route('index'));
}
/**
* Show debug info.
*
* @return Factory|View
*
* @throws FilesystemException
*/
public function index(): Factory|\Illuminate\Contracts\View\View
{
$table = $this->generateTable();
$table = str_replace(["\n", "\t", ' '], '', $table);
$now = now(config('app.timezone'))->format('Y-m-d H:i:s');
// get latest log file:
$logger = Log::driver();
// PHPstan doesn't recognize the method because of its polymorphic nature.
$handlers = $logger->getHandlers(); // @phpstan-ignore-line
$logContent = '';
foreach ($handlers as $handler) {
if ($handler instanceof RotatingFileHandler) {
$logFile = $handler->getUrl();
if (null !== $logFile && file_exists($logFile)) {
$logContent = file_get_contents($logFile);
}
}
}
if ('' !== $logContent) {
// last few lines
$logContent = 'Truncated from this point <----|'.substr($logContent, -16384);
}
return view('debug', ['table' => $table, 'now' => $now, 'logContent' => $logContent]);
}
public function routes(Request $request): never
{
if (!auth()->user()->hasRole('owner')) {
throw new NotFoundHttpException();
}
/** @var iterable $routes */
$routes = Route::getRoutes();
if ('true' === $request->get('api')) {
$collection = [];
$i = 0;
echo 'PATHS="';
/** @var \Illuminate\Routing\Route $route */
foreach ($routes as $route) {
++$i;
// skip API and other routes.
if (!str_starts_with($route->uri(), 'api/v1')) {
continue;
}
// skip non GET routes
if (!in_array('GET', $route->methods(), true)) {
continue;
}
// no name route:
if (null === $route->getName()) {
var_dump($route);
exit;
}
echo substr($route->uri(), 3);
if (0 === ($i % 5)) {
echo '"
PATHS="${PATHS},';
}
if (0 !== ($i % 5)) {
echo ',';
}
}
exit;
}
$return = [];
/** @var \Illuminate\Routing\Route $route */
foreach ($routes as $route) {
// skip API and other routes.
if (
str_starts_with($route->uri(), 'api')
|| str_starts_with($route->uri(), '_debugbar')
|| str_starts_with($route->uri(), '_ignition')
|| str_starts_with($route->uri(), 'oauth')
|| str_starts_with($route->uri(), 'chart')
|| str_starts_with($route->uri(), 'v1/jscript')
|| str_starts_with($route->uri(), 'v2/jscript')
|| str_starts_with($route->uri(), 'json')
|| str_starts_with($route->uri(), 'sanctum')
) {
continue;
}
// skip non GET routes
if (!in_array('GET', $route->methods(), true)) {
continue;
}
// no name route:
if (null === $route->getName()) {
var_dump($route);
exit;
}
if (!str_contains($route->uri(), '{')) {
$return[$route->getName()] = route($route->getName());
continue;
}
$params = [];
foreach ($route->parameterNames() as $name) {
$params[] = $this->getParameter($name);
}
$return[$route->getName()] = route($route->getName(), $params);
}
$count = 0;
echo '