Returns the first/last event record for the given event fact.

@param string $fact
@param string $operation

@return Model|object|static|null
778268
private function eventQuery(string $fact, string $operation)
    {
        return DB::table('dates')
            ->select(['d_gid as id', 'd_year as year', 'd_fact AS fact', 'd_type AS type'])
            ->where('d_file', '=', $this->tree->id())
            ->where('d_fact', '=', $fact)
            ->where('d_julianday1', '=', function (Builder $query) use ($operation, $fact): void {
                $query->selectRaw($operation . '(d_julianday1)')
                    ->from('dates')
                    ->where('d_file', '=', $this->tree->id())
                    ->where('d_fact', '=', $fact)
                    ->where('d_julianday1', '<>', 0);
            })
            ->first();
    }
829556
public function getOperation()
    {
        switch ($this->operation['type']) {
            case self::QUERY_UPDATE :
                return AnDomain::OPERATION_UPDATE;
            case self::QUERY_DELETE :
                return AnDomain::OPERATION_DELETE;
            default :
                return AnDomain::OPERATION_FETCH;
        }
    }
35140
protected function getLogObject(LdapOperationInterface $operation)
    {
        if (!$this->logger) {
            return null;
        }

        return (new LogOperation($operation))->setDomain($this->connection->getConfig()->getDomainName());
    }
497160
protected function doCall($operation)
    {
        $this->client->send($operation);
        $result = $this->client->recv();
        if(false === $result)
        {
            return false;
        }
        if(null === $result->throwable)
        {
            return $result->result;
        }
        else
        {
            throw $result->throwable;
        }
    }
13313
protected function releaseLock($operation)
    {
        $exists = is_resource($this->lockHandle);

        $success = $exists && flock($this->lockHandle, $operation);

        $exists && fclose($this->lockHandle);
        $this->lockHandle = null;

        return $success;
    }
1307535
public function last($object = false)
    {
        $this->prepare();

        $data = $this->_map;
        if (count($data) > 0) {
            return $this->prepareResult(end($data), $object);
        }

        return null;
    }
1192489
private function runOperation(Operation $operation)
    {
        try {
            return $this->runner->run($operation);
        } catch (\Throwable $e) {
            // treated below
        } catch (\Exception $e) {
            // treated below
        }

        // @todo keep only inner if once ExceptionCatcher is gone
        if ($this->exceptionCatcherVoter instanceof ThrowableCatcherVoter) {
            if (!$this->exceptionCatcherVoter->shouldCatchThrowable($e)) {
                throw $e;
            }
        } elseif (!$this->exceptionCatcherVoter->shouldCatch($e)) {
            throw $e;
        }

        try {
            $this->waitStrategy->wait();
        } catch (WaiterException $waiterException) {
            throw $e;
        }

        return $this->runOperation($operation);
    }
1236541
public function lastChangeTimestamp(): Carbon
    {
        /** @var Fact|null $chan */
        $chan = $this->facts(['CHAN'])->first();

        if ($chan instanceof Fact) {
            // The record does have a CHAN event
            $d = $chan->date()->minimumDate();

            if (preg_match('/\n3 TIME (\d\d):(\d\d):(\d\d)/', $chan->gedcom(), $match)) {
                return Carbon::create($d->year(), $d->month(), $d->day(), (int) $match[1], (int) $match[2], (int) $match[3]);
            }

            if (preg_match('/\n3 TIME (\d\d):(\d\d)/', $chan->gedcom(), $match)) {
                return Carbon::create($d->year(), $d->month(), $d->day(), (int) $match[1], (int) $match[2]);
            }

            return Carbon::create($d->year(), $d->month(), $d->day());
        }

        // The record does not have a CHAN event
        return Carbon::createFromTimestamp(0);
    }
793563
private function formatSexRecord(Fact $fact): string
    {
        $individual = $fact->record();

        switch ($fact->value()) {
            case 'M':
                $sex = I18N::translate('Male');
                break;
            case 'F':
                $sex = I18N::translate('Female');
                break;
            default:
                $sex = I18N::translateContext('unknown gender', 'Unknown');
                break;
        }

        $container_class = 'card';
        if ($fact->isPendingDeletion()) {
            $container_class .= ' old';
        } elseif ($fact->isPendingAddition()) {
            $container_class .= ' new';
        }

        if ($individual->canEdit()) {
            $edit_links = '<a class="btn btn-link" href="' . e(route('edit-fact', ['xref' => $individual->xref(), 'fact_id' => $fact->id(), 'ged' => $individual->tree()->name()])) . '" title="' . I18N::translate('Edit the gender') . '">' . view('icons/edit') . '<span class="sr-only">' . I18N::translate('Edit the gender') . '</span></a>';
        } else {
            $edit_links = '';
        }

        return '
		<div class="' . $container_class . '">
			<div class="card-header" role="tab" id="name-header-add">
				<div class="card-title mb-0">
					<b>' . I18N::translate('Gender') . '</b> ' . $sex . $edit_links . '
				</div>
			</div>
		</div>';
    }
848189
public function getFirst()
    {
        if (is_array($this->queryResult)) {
            $queryResult = &$this->queryResult;
        } else {
            $query = clone $this->query;
            $query->setLimit(1);
            $queryResult = $this->dataMapper->mapToObjects($this->persistenceManager->getObjectDataByQuery($query));
        }
        return (isset($queryResult[0])) ? $queryResult[0] : null;
    }
1042796
public static function createEditForm(Fact $fact): void
    {
        $record = $fact->record();
        $tree   = $record->tree();

        self::$tags = [];

        $level0type = $record::RECORD_TYPE;
        $level1type = $fact->getTag();

        // List of tags we would expect at the next level
        // NB insertMissingSubtags() already takes care of the simple cases
        // where a level 1 tag is missing a level 2 tag. Here we only need to
        // handle the more complicated cases.
        $expected_subtags = [
            'SOUR' => [
                'PAGE',
                'DATA',
            ],
            'PLAC' => ['MAP'],
            'MAP'  => [
                'LATI',
                'LONG',
            ],
        ];
        
        if ($record::RECORD_TYPE !== 'SOUR') {
            //source citations within other records, i.e. n SOUR / +1 DATA / +2 TEXT
            $expected_subtags['DATA'][] = 'TEXT';
        } //else: source records themselves, i.e. 0 SOUR / 1 DATA don't get a 2 TEXT!

        if ($record::RECORD_TYPE === 'SOUR') {
            //source records themselves, i.e. 0 SOUR / 1 DATA / 2 EVEN get a 3 DATE and a 3 PLAC
            $expected_subtags['EVEN'][] = 'DATE';
            $expected_subtags['EVEN'][] = 'PLAC';
        }
        
        if ($record->tree()->getPreference('FULL_SOURCES')) {
            $expected_subtags['SOUR'][] = 'QUAY';
            
            if ($record::RECORD_TYPE !== 'SOUR') {
                //source citations within other records, i.e. n SOUR / +1 DATA / +2 DATE
                $expected_subtags['DATA'][] = 'DATE';
            } //else: source records themselves, i.e. 0 SOUR / 1 DATA don't get a 2 DATE!
        }

        if (GedcomCodeTemp::isTagLDS($level1type)) {
            $expected_subtags['STAT'] = ['DATE'];
        }

        if (in_array($level1type, Config::dateAndTime(), true)) {
            // TIME is NOT a valid 5.5.1 tag
            $expected_subtags['DATE'] = ['TIME'];
        }

        if (preg_match_all('/(' . Gedcom::REGEX_TAG . ')/', $record->tree()->getPreference('ADVANCED_PLAC_FACTS'), $match)) {
            $expected_subtags['PLAC'] = array_merge($match[1], $expected_subtags['PLAC']);
        }

        $stack       = [];
        $gedlines    = explode("\n", $fact->gedcom());
        $count       = count($gedlines);
        $i           = 0;
        $inSource    = false;
        $levelSource = 0;
        $add_date    = true;

        // Loop on existing tags :
        while ($i < $count) {
            $fields = explode(' ', $gedlines[$i], 3);
            $level  = (int) $fields[0];
            $type   = $fields[1] ?? '';
            $text   = $fields[2] ?? '';

            // Keep track of our hierarchy, e.g. 1=>BIRT, 2=>PLAC, 3=>FONE
            $stack[$level] = $type;
            // Merge them together, e.g. BIRT:PLAC:FONE
            $label = implode(':', array_slice($stack, 0, $level));

            // Merge text from continuation lines
            while ($i + 1 < $count && preg_match('/^' . ($level + 1) . ' CONT ?(.*)/', $gedlines[$i + 1], $cmatch) > 0) {
                $text .= "\n" . $cmatch[1];
                $i++;
            }

            if ($type === 'SOUR') {
                $inSource    = true;
                $levelSource = $level;
            } elseif ($levelSource >= $level) {
                $inSource = false;
            }

            self::$tags[] = $type;
            $subrecord    = $level . ' ' . $type . ' ' . $text;

            // Dates need different labels, depending on whether they are inside sources.
            if ($inSource && $type === 'DATE') {
                echo self::addSimpleTag($tree, $subrecord, '', GedcomTag::getLabel($label, $record));
            } elseif (!$inSource && $type === 'DATE') {
                echo self::addSimpleTag($tree, $subrecord, $level1type, GedcomTag::getLabel($label, $record));
                if ($level === 2) {
                    // We already have a date - no need to add one.
                    $add_date = false;
                }
            } elseif ($type === 'STAT') {
                echo self::addSimpleTag($tree, $subrecord, $level1type, GedcomTag::getLabel($label, $record));
            } else {
                echo self::addSimpleTag($tree, $subrecord, $level0type, GedcomTag::getLabel($label, $record));
            }

            // Get a list of tags present at the next level
            $subtags = [];
            for ($ii = $i + 1; isset($gedlines[$ii]) && preg_match('/^(\d+) (\S+)/', $gedlines[$ii], $mm) && $mm[1] > $level; ++$ii) {
                if ($mm[1] == $level + 1) {
                    $subtags[] = $mm[2];
                }
            }

            // Insert missing tags
            if (!empty($expected_subtags[$type])) {
                foreach ($expected_subtags[$type] as $subtag) {
                    if (!in_array($subtag, $subtags, true)) {
                        echo self::addSimpleTag($tree, ($level + 1) . ' ' . $subtag, '', GedcomTag::getLabel($label . ':' . $subtag));
                        if (!empty($expected_subtags[$subtag])) {
                            foreach ($expected_subtags[$subtag] as $subsubtag) {
                                echo self::addSimpleTag($tree, ($level + 2) . ' ' . $subsubtag, '', GedcomTag::getLabel($label . ':' . $subtag . ':' . $subsubtag));
                            }
                        }
                    }
                }
            }

            $i++;
        }

        if ($level1type !== '_PRIM') {
            //0 SOUR / 1 DATA doesn't get a 2 DATE!
            //0 SOUR / 1 DATA doesn't get a 2 EVEN here either, we rather handle this via cards/add-sour-data-even
            if ($record::RECORD_TYPE !== 'SOUR') {
                self::insertMissingSubtags($tree, $level1type, $add_date);
            }
        }
    }
828035
public function remove(OperationState $operation = NULL)
    {
        if (is_null($operation)) {
            array_pop($this->operationQueue);
            return TRUE;
        } else {
            if ($this->isInQueue($operation)) {
                unset($this->operationQueue[$operation->getKey()]);
                return TRUE;
            }
            return FALSE;
        }
    }
385529
private function includeFact(Fact $fact, Date $min_date, Date $max_date): bool
    {
        $fact_date = $fact->date();

        return $fact_date->isOK() && Date::compare($min_date, $fact_date) <= 0 && Date::compare($fact_date, $max_date) <= 0;
    }
700614
public function setOperation(\CampaignChain\CoreBundle\Entity\Operation $operation = null)
    {
        $this->operation = $operation;

        $this->setStartDate($this->operation->getStartDate());

        return $this;
    }
1279782
private function findOperationAttribute(?array $operations, ?string $operationName, string $key, $defaultValue, bool $resourceFallback)
    {
        if (null !== $operationName && isset($operations[$operationName][$key])) {
            return $operations[$operationName][$key];
        }

        if ($resourceFallback && isset($this->attributes[$key])) {
            return $this->attributes[$key];
        }

        return $defaultValue;
    }
569004
public static function getDecimals( $fact )
	{
		if ( ! $fact instanceof DOMXPathNavigator )
		{
			throw new \Exception( "Invalid fact variable passed to FactValues::getDecimals" );
		}

		$fact = $fact->CloneInstance();
		if ( $fact->MoveToAttribute( "decimals", null ) )
		{
			return $fact->getValue();
		}

		return false;
	}
1238650
private function calendarFactText(Fact $fact, bool $show_places): string
    {
        $text = $fact->label() . ' — ' . $fact->date()->display(true, null, false);
        if ($fact->anniv) {
            $text .= ' (' . I18N::translate('%s year anniversary', $fact->anniv) . ')';
        }
        if ($show_places && $fact->attribute('PLAC')) {
            $text .= ' — ' . $fact->attribute('PLAC');
        }

        return $text;
    }