jon48/webtrees-lib

View on GitHub
app/Module/AdminTasks/Services/HealthCheckService.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

/**
 * webtrees-lib: MyArtJaub library for webtrees
 *
 * @package MyArtJaub\Webtrees
 * @subpackage AdminTasks
 * @author Jonathan Jaubart <dev@jaubart.com>
 * @copyright Copyright (c) 2020-2022, Jonathan Jaubart
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3
 */

declare(strict_types=1);

namespace MyArtJaub\Webtrees\Module\AdminTasks\Services;

use Carbon\Carbon;
use Fisharebest\Webtrees\Tree;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Database\Query\Builder;
use Illuminate\Database\Query\Expression;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;

/**
 * Service for retrieving data for the Healthcheck task
 */
class HealthCheckService
{
    /**
     * Returns a query collating all gedcom records, for use in other queries
     *
     * @param Tree $tree
     * @return Builder
     */
    private function allGedcomRecords(Tree $tree): Builder
    {
        return DB::table('individuals')
            ->select(DB::raw("'indi' AS ged_type"), 'i_id AS ged_id')->where('i_file', '=', $tree->id())
            ->unionAll(DB::table('families')
                ->select(DB::raw("'fam' AS ged_type"), 'f_id AS ged_id')->where('f_file', '=', $tree->id()))
            ->unionAll(DB::table('sources')
                ->select(DB::raw("'sour' AS ged_type"), 's_id AS ged_id')->where('s_file', '=', $tree->id()))
            ->unionAll(DB::table('media')
                ->select(DB::raw("'media' AS ged_type"), 'm_id AS ged_id')->where('m_file', '=', $tree->id()))
            ->unionAll(DB::table('other')
                ->select(DB::raw('LOWER(o_type) AS ged_type'), 'o_id AS ged_id')->where('o_file', '=', $tree->id()));
    }

    /**
     * Returns the count of gedcom records by type in a Tree, as a keyed Collection.
     *
     * Collection output:
     *      - Key : gedcom record type
     *      - Value: count of records
     *
     * @param Tree $tree
     * @return Collection<string, int>
     */
    public function countByRecordType(Tree $tree): Collection
    {
        return DB::query()
            ->fromSub($this->allGedcomRecords($tree), 'gedrecords')
            ->select('ged_type', new Expression('COUNT(ged_id) AS total'))
            ->groupBy('ged_type')
            ->pluck('total', 'ged_type');
    }

    /**
     * Returns the count of gedcom records changes by type in a Tree across a number of days, as a keyed Collection.
     *
     * Collection output:
     *      - Key : gedcom record type
     *      - Value: count of changes
     *
     * @param Tree $tree
     * @return Collection<string, int>
     */
    public function changesByRecordType(Tree $tree, int $nb_days): Collection
    {
        return DB::table('change')
            ->joinSub($this->allGedcomRecords($tree), 'gedrecords', function (JoinClause $join) use ($tree): void {

                $join->on('change.xref', '=', 'gedrecords.ged_id')
                    ->where('change.gedcom_id', '=', $tree->id());
            })
            ->select('ged_type AS type', new Expression('COUNT(change_id) AS count'))
            ->where('change.status', '', 'accepted')
            ->where('change.change_time', '>=', Carbon::now()->subDays($nb_days))
            ->groupBy('ged_type')
            ->pluck('total', 'ged_type');
    }

    /**
     * Return the error logs associated with a tree across a number of days, grouped by error message, as a Collection.
     *
     * Collection output:
     *      - Value: stdClass object
     *          - log message:  Error log message
     *          - type:         'site' if no associated Tree, the Tree ID otherwise
     *          - nblogs:       The number of occurrence of the same error message
     *          - lastoccurred: Date/time of the last occurrence of the error message
     *
     * @param Tree $tree
     * @param int $nb_days
     * @return Collection<\stdClass>
     */
    public function errorLogs(Tree $tree, int $nb_days): Collection
    {
        return DB::table('log')
            ->select(
                'log_message',
                new Expression("IFNULL(gedcom_id, 'site') as type"),
                new Expression('COUNT(log_id) AS nblogs'),
                new Expression('MAX(log_time) AS lastoccurred')
            )
            ->where('log_type', '=', 'error')
            ->where(function (Builder $query) use ($tree): void {
                $query->where('gedcom_id', '=', $tree->id())
                    ->orWhereNull('gedcom_id');
            })
            ->where('log_time', '>=', Carbon::now()->subDays($nb_days))
            ->groupBy('log_message', 'gedcom_id')
            ->orderByDesc('lastoccurred')
            ->get();
    }
}