Return HTML code to include a flag icon in facts description

@param \Fisharebest\Webtrees\Fact $fact Fact record
@param \MyArtJaub\Webtrees\Map\MapProviderInterface $mapProvider Map Provider
@return string HTML code of the inserted flag
435119
public static function htmlFactPlaceIcon(
			\Fisharebest\Webtrees\Fact $fact,
			\MyArtJaub\Webtrees\Map\MapProviderInterface $mapProvider
	) {
		$place = $fact->getPlace();
		if(!$place->isEmpty()) {
			$iconPlace= $mapProvider->getPlaceIcon($place);	
			if($iconPlace && strlen($iconPlace) > 0){
				return	'<div class="fact_flag">'. self::htmlPlaceIcon($place, $iconPlace, 50). '</div>';
			}
		}
		return '';
	}
73001
def __declare(self, *facts):
        
        if any(f.has_field_constraints() for f in facts):
            raise TypeError(
                "Declared facts cannot contain conditional elements")
        elif any(f.has_nested_accessor() for f in facts):
            raise KeyError(
                "Cannot declare facts containing double underscores as keys.")
        else:
            last_inserted = None
            for fact in facts:
                last_inserted = self.facts.declare(fact)

            if not self.running:
                added, removed = self.get_activations()
                self.strategy.update_agenda(self.agenda, added, removed)

            return last_inserted
1332183
public function getAspectsCovered( $variableSet, $factVariableBinding )
	{
		if ( $this->dimension )
		{
			// $qname = qname( $this->dimension );
			return array( "{{$this->dimension['namespace']}}{$this->dimension['name']}" );
		}
		else if ( $this->dimensionXPath2Expression )
		{
			/**
			 * @var XPath2Item $result
			 */
			$result = $this->evaluateXPathExpression( $variableSet, $this->dimensionXPath2Expression );
			return array( (string)$result->getValue() );
		}
		else if ( $this->dimensionExpression )
		{
			/**
			 * @var XPath2Item $result
			 */
			$result = $this->evaluateXPath( $variableSet, $this->dimensionExpression );
			return array( (string)$result->getValue() );
		}

		return array( ASPECT_DIMENSIONS );
	}
303317
private function evaluateAcceptanceRadius( $variableSet, $derivedValue, $fact, $factVars = array() )
	{
		if ( is_null( $this->radiusValue ) )
		{
			if ( ! is_null( $this->absoluteAcceptanceRadius ) || ! is_null( $this->proportionalAcceptanceRadius ) )
			{
				$expression = ! is_null( $this->absoluteAcceptanceRadius )
					? $this->absoluteAcceptanceRadius
					: $this->proportionalAcceptanceRadius;

				$expression = "$expression cast as xs:float";

				$vars = array_map( function( $param ) { return $param->result; }, $this->parameters );
				$vars = array_merge( $factVars, $vars );
				// $result = $this->evaluateXPath( $variableSet, $expression, $vars );
				$provider = new NodeProvider( $fact );

				$xpathExpression = XPath2Expression::Compile( $expression, $variableSet->nsMgr );

				$xpathExpression->AddToContext( "xbrlInstance", $variableSet->xbrlInstance );
				$xpathExpression->AddToContext( "xbrlTaxonomy", $variableSet->xbrlTaxonomy );
				$xpathExpression->AddToContext( "base", $variableSet->base );
				$result = $xpathExpression->EvaluateWithVars( $provider, $vars );

				$this->radiusValue = $result instanceof XPath2Item ? $result->getTypedValue() : $result;
			}
			else
			{
				$this->radiusValue = false;
			}
		}

		if ( ! is_null( $this->absoluteAcceptanceRadius ) )
		{
			return $this->radiusValue;
		}

		if ( ! is_null( $this->proportionalAcceptanceRadius ) )
		{
			return $this->radiusValue * $derivedValue;
		}

		return null;
	}
234753
public static function printMainSources(Fact $fact, int $level): void
    {
        $factrec = $fact->gedcom();
        $parent  = $fact->record();
        $tree    = $fact->record()->tree();

        $nlevel = $level + 1;
        if ($fact->isPendingAddition()) {
            $styleadd = 'wt-new';
            $can_edit = $level === 1 && $fact->canEdit();
        } elseif ($fact->isPendingDeletion()) {
            $styleadd = 'wt-old';
            $can_edit = false;
        } else {
            $styleadd = '';
            $can_edit = $level === 1 && $fact->canEdit();
        }

        // -- find source for each fact
        $ct    = preg_match_all("/($level SOUR (.+))/", $factrec, $match, PREG_SET_ORDER);
        $spos2 = 0;
        for ($j = 0; $j < $ct; $j++) {
            $sid   = trim($match[$j][2], '@');
            $spos1 = strpos($factrec, $match[$j][1], $spos2);
            $spos2 = strpos($factrec, "\n$level", $spos1);
            if (!$spos2) {
                $spos2 = strlen($factrec);
            }
            $srec   = substr($factrec, $spos1, $spos2 - $spos1);
            $source = Source::getInstance($sid, $tree);
            // Allow access to "1 SOUR @non_existent_source@", so it can be corrected/deleted
            if (!$source || $source->canShow()) {
                if ($level > 1) {
                    echo '<tr class="wt-level-two-source collapse">';
                } else {
                    echo '<tr>';
                }
                echo '<th class="';
                if ($level > 1) {
                    echo ' rela';
                }
                echo ' ', $styleadd, '">';
                $factlines = explode("\n", $factrec); // 1 BIRT Y\n2 SOUR ...
                $factwords = explode(' ', $factlines[0]); // 1 BIRT Y
                $factname  = $factwords[1]; // BIRT
                if ($factname === 'EVEN' || $factname === 'FACT') {
                    // Add ' EVEN' to provide sensible output for an event with an empty TYPE record
                    $ct = preg_match('/2 TYPE (.*)/', $factrec, $ematch);
                    if ($ct > 0) {
                        $factname = trim($ematch[1]);
                        echo $factname;
                    } else {
                        echo GedcomTag::getLabel($factname, $parent);
                    }
                } elseif ($can_edit) {
                    echo '<a href="' . e(route('edit-fact', [
                            'xref'    => $parent->xref(),
                            'fact_id' => $fact->id(),
                            'ged'     => $tree->name(),
                        ])) . '" title="', I18N::translate('Edit'), '">';
                    if ($tree->getPreference('SHOW_FACT_ICONS') && $level === 1) {
                        echo '<i class="icon-source"></i> ';
                    }
                    echo GedcomTag::getLabel($factname, $parent), '</a>';
                    echo '<div class="editfacts">';
                    if (preg_match('/^@.+@$/', $match[$j][2])) {
                        // Inline sources can't be edited. Attempting to save one will convert it
                        // into a link, and delete it.
                        // e.g. "1 SOUR my source" becomes "1 SOUR @my source@" which does not exist.
                        echo view('edit/icon-fact-edit', ['fact' => $fact]);
                        echo view('edit/icon-fact-copy', ['fact' => $fact]);
                    }
                    echo view('edit/icon-fact-delete', ['fact' => $fact]);
                } else {
                    echo GedcomTag::getLabel($factname, $parent);
                }
                echo '</th>';
                echo '<td class="', $styleadd, '">';
                if ($source) {
                    echo '<a href="', e($source->url()), '">', $source->fullName(), '</a>';
                    // PUBL
                    $publ = $source->facts(['PUBL'])->first();
                    if ($publ) {
                        echo GedcomTag::getLabelValue('PUBL', $publ->value());
                    }
                    // 2 RESN tags. Note, there can be more than one, such as "privacy" and "locked"
                    if (preg_match_all("/\n2 RESN (.+)/", $factrec, $rmatches)) {
                        foreach ($rmatches[1] as $rmatch) {
                            echo '<br><span class="label">', GedcomTag::getLabel('RESN'), ':</span> <span class="field">';
                            switch ($rmatch) {
                                case 'none':
                                    // Note: "2 RESN none" is not valid gedcom, and the GUI will not let you add it.
                                    // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public".
                                    echo '<i class="icon-resn-none"></i> ', I18N::translate('Show to visitors');
                                    break;
                                case 'privacy':
                                    echo '<i class="icon-resn-privacy"></i> ', I18N::translate('Show to members');
                                    break;
                                case 'confidential':
                                    echo '<i class="icon-resn-confidential"></i> ', I18N::translate('Show to managers');
                                    break;
                                case 'locked':
                                    echo '<i class="icon-resn-locked"></i> ', I18N::translate('Only managers can edit');
                                    break;
                                default:
                                    echo $rmatch;
                                    break;
                            }
                            echo '</span>';
                        }
                    }
                    $cs = preg_match("/$nlevel EVEN (.*)/", $srec, $cmatch);
                    if ($cs > 0) {
                        echo '<br><span class="label">', GedcomTag::getLabel('EVEN'), ' </span><span class="field">', $cmatch[1], '</span>';
                        $cs = preg_match('/' . ($nlevel + 1) . ' ROLE (.*)/', $srec, $cmatch);
                        if ($cs > 0) {
                            echo '<br>&nbsp;&nbsp;&nbsp;&nbsp;<span class="label">', GedcomTag::getLabel('ROLE'), ' </span><span class="field">', $cmatch[1], '</span>';
                        }
                    }
                    echo self::printSourceStructure($tree, self::getSourceStructure($srec));
                    echo '<div class="indent">';
                    self::printMediaLinks($tree, $srec, $nlevel);
                    if ($nlevel === 2) {
                        self::printMediaLinks($tree, $source->gedcom(), 1);
                    }
                    echo FunctionsPrint::printFactNotes($tree, $srec, $nlevel);
                    if ($nlevel === 2) {
                        echo FunctionsPrint::printFactNotes($tree, $source->gedcom(), 1);
                    }
                    echo '</div>';
                } else {
                    echo $sid;
                }
                echo '</td></tr>';
            }
        }
    }
848364
private function queryFactPlaces(string $fact, string $what = 'ALL', bool $country = false): array
    {
        $rows = [];

        if ($what === 'INDI') {
            $rows = DB::table('individuals')->select(['i_gedcom as ged'])->where(
                'i_file',
                '=',
                $this->tree->id()
            )->where(
                'i_gedcom',
                'LIKE',
                "%\n2 PLAC %"
            )->get()->all();
        } elseif ($what === 'FAM') {
            $rows = DB::table('families')->select(['f_gedcom as ged'])->where(
                'f_file',
                '=',
                $this->tree->id()
            )->where(
                'f_gedcom',
                'LIKE',
                "%\n2 PLAC %"
            )->get()->all();
        }

        $placelist = [];

        foreach ($rows as $row) {
            if (preg_match('/\n1 ' . $fact . '(?:\n[2-9].*)*\n2 PLAC (.+)/', $row->ged, $match)) {
                if ($country) {
                    $tmp   = explode(Gedcom::PLACE_SEPARATOR, $match[1]);
                    $place = end($tmp);
                } else {
                    $place = $match[1];
                }

                if (isset($placelist[$place])) {
                    ++$placelist[$place];
                } else {
                    $placelist[$place] = 1;
                }
            }
        }

        return $placelist;
    }
1348789
public function pasteFact(string $fact_id, GedcomRecord $record): bool
    {
        $clipboard = Session::get('clipboard');

        $record_type = $record::RECORD_TYPE;

        if (isset($clipboard[$record_type][$fact_id])) {
            $record->createFact($clipboard[$record_type][$fact_id]['factrec'], true);

            return true;
        }

        return false;
    }
1189199
public static function getPicklistFacts($fact_type): array
    {
        switch ($fact_type) {
            case 'INDI':
                $tags = [
                    // Facts, attributes for individuals (no links to FAMs)
                    'RESN',
                    'NAME',
                    'SEX',
                    'BIRT',
                    'CHR',
                    'DEAT',
                    'BURI',
                    'CREM',
                    'ADOP',
                    'BAPM',
                    'BARM',
                    'BASM',
                    'BLES',
                    'CHRA',
                    'CONF',
                    'FCOM',
                    'ORDN',
                    'NATU',
                    'EMIG',
                    'IMMI',
                    'CENS',
                    'PROB',
                    'WILL',
                    'GRAD',
                    'RETI',
                    'EVEN',
                    'CAST',
                    'DSCR',
                    'EDUC',
                    'IDNO',
                    'NATI',
                    'NCHI',
                    'NMR',
                    'OCCU',
                    'PROP',
                    'RELI',
                    'RESI',
                    'SSN',
                    'TITL',
                    'FACT',
                    'BAPL',
                    'CONL',
                    'ENDL',
                    'SLGC',
                    'SUBM',
                    'ASSO',
                    'ALIA',
                    'ANCI',
                    'DESI',
                    'RFN',
                    'AFN',
                    'REFN',
                    'RIN',
                    'CHAN',
                    'NOTE',
                    'SHARED_NOTE',
                    'SOUR',
                    'OBJE',
                    // non standard tags
                    '_BRTM',
                    '_DEG',
                    '_DNA',
                    '_EYEC',
                    '_FNRL',
                    '_HAIR',
                    '_HEIG',
                    '_HNM',
                    '_HOL',
                    '_INTE',
                    '_MDCL',
                    '_MEDC',
                    '_MILI',
                    '_MILT',
                    '_NAME',
                    '_NAMS',
                    '_NLIV',
                    '_NMAR',
                    '_PRMN',
                    '_TODO',
                    '_UID',
                    '_WEIG',
                    '_YART',
                ];
                break;
            case 'FAM':
                $tags = [
                    // Facts for families, left out HUSB, WIFE & CHIL links
                    'RESN',
                    'ANUL',
                    'CENS',
                    'DIV',
                    'DIVF',
                    'ENGA',
                    'MARB',
                    'MARC',
                    'MARR',
                    'MARL',
                    'MARS',
                    'RESI',
                    'EVEN',
                    'NCHI',
                    'SUBM',
                    'SLGS',
                    'REFN',
                    'RIN',
                    'CHAN',
                    'NOTE',
                    'SHARED_NOTE',
                    'SOUR',
                    'OBJE',
                    // non standard tags
                    '_NMR',
                    'MARR_CIVIL',
                    'MARR_RELIGIOUS',
                    'MARR_PARTNERS',
                    'MARR_UNKNOWN',
                    '_COML',
                    '_MBON',
                    '_MARI',
                    '_SEPR',
                    '_TODO',
                ];
                break;
            case 'SOUR':
                $tags = [
                    // Facts for sources
                    'DATA',
                    'AUTH',
                    'TITL',
                    'ABBR',
                    'PUBL',
                    'TEXT',
                    'REPO',
                    'REFN',
                    'RIN',
                    'CHAN',
                    'NOTE',
                    'SHARED_NOTE',
                    'OBJE',
                    'RESN',
                ];
                break;
            case 'REPO':
                $tags = [
                    // Facts for repositories
                    'NAME',
                    'ADDR',
                    'PHON',
                    'EMAIL',
                    'FAX',
                    'WWW',
                    'NOTE',
                    'SHARED_NOTE',
                    'REFN',
                    'RIN',
                    'CHAN',
                    'RESN',
                ];
                break;
            case 'PLAC':
                $tags = [
                    // Facts for places
                    'FONE',
                    'ROMN',
                    // non standard tags
                    '_HEB',
                ];
                break;
            case 'NAME':
                $tags = [
                    // Facts subordinate to NAME
                    'FONE',
                    'ROMN',
                    // non standard tags
                    '_HEB',
                    '_AKA',
                    '_MARNM',
                ];
                break;
            default:
                $tags = [];
                break;
        }

        $facts = [];
        foreach ($tags as $tag) {
            $facts[$tag] = self::getLabel($tag, null);
        }
        uasort($facts, '\Fisharebest\Webtrees\I18N::strcasecmp');

        return $facts;
    }
981283
public FactPattern getLHSParentFactPatternForBinding(final String var) {
        if (this.lhs == null) {
            return null;
        }
        for (int i = 0; i < this.lhs.length; i++) {
            IPattern pat = this.lhs[i];
            if (pat instanceof FromCompositeFactPattern) {
                pat = ((FromCompositeFactPattern) pat).getFactPattern();
            }
            if (pat instanceof FactPattern) {
                final FactPattern p = (FactPattern) pat;
                if (p.getBoundName() != null && var.equals(p.getBoundName())) {
                    return p;
                }
                for (int j = 0; j < p.getFieldConstraints().length; j++) {
                    FieldConstraint fc = p.getFieldConstraints()[j];
                    List<String> fieldBindings = getFieldBinding(fc);
                    if (fieldBindings.contains(var)) {
                        return p;
                    }
                }
            }
        }
        return null;
    }
565762
function(fact) {
        var subject, predicate, object;

        /*if (fact.fromTriple !== undefined) {
            return fact.fromTriple;
        }*/

        if(fact.falseFact) {
            return '';
        }

        subject = this.parseStrEntityToTurtle(fact.subject);
        predicate = this.parseStrEntityToTurtle(fact.predicate);
        object = this.parseStrEntityToTurtle(fact.object);

        if (subject && predicate && object) {
            return subject + ' ' + predicate + ' ' + object + ' . ';
        } else {
            return '';
        }
    }
961428
public function render(InfoWindow $infoWindow, Map $map, Marker $marker = null)
    {
        $arguments = [$map->getVariable()];

        if ($marker !== null) {
            $arguments[] = $marker->getVariable();
        }

        return $this->getFormatter()->renderObjectCall($infoWindow, 'open', $arguments);
    }
400439
public function Filter( $facts, $variableSet )
	{
		// Look for the variable
		$vars = $variableSet->getBindingsAsVars();
		$clark = str_replace( "{}", "", "{{$this->variable['namespace']}}{$this->variable['name']}" );
		if ( ! isset( $vars[ $clark ] ) )
		{
			// Should probably throw some kind of error here
			throw XPath2Exception::withErrorCodeAndParam( "XPST0008", Resources::XPST0008, $clark );
		}

		/**
		 * @var \DOMNode[] $candidates
		 */
		$candidate = null;
		$var = $vars[ $clark ];
		if ( $var instanceof XPath2NodeIterator )
		{
			$node = reset( $var->ToList() );
			if ( is_null( $node ) )
			{
				throw XPath2Exception::withErrorCodeAndParam( "XPST0008", Resources::XPST0008, $clark );
			}

			$candidate = $node->getUnderlyingObject();
		}
		else
		{
			$candidate = $var->getUnderlyingObject();
		}

		$matched = array();
		$notMatched = array();

		$candidateParent = $candidate->parentNode;

		// The fact can be an
		foreach ( $facts as $fact )
		{
			$node = $fact->getUnderlyingObject();
			$factParent = $node->parentNode;

			if ( $candidateParent->isSameNode( $factParent ) )
			{
				$matched[] = $fact->CloneInstance();
			}
			else
			{
				$notMatched[] = $fact->CloneInstance();
			}
		}

		return DocumentOrderNodeIterator::fromItemset( $this->complement ? $notMatched : $matched );

		return $facts;
	}
547592
private function formatNameRecord(Tree $tree, $n, Fact $fact): string
    {
        $individual = $fact->record();

        // Create a dummy record, so we can extract the formatted NAME value from it.
        $dummy = new Individual(
            'xref',
            "0 @xref@ INDI\n1 DEAT Y\n" . $fact->gedcom(),
            null,
            $individual->tree()
        );
        $dummy->setPrimaryName(0); // Make sure we use the name from "1 NAME"

        $container_class = 'card';
        $content_class   = 'collapse';
        $aria            = 'false';

        if ($n === 0) {
            $content_class = 'collapse show';
            $aria          = 'true';
        }
        if ($fact->isPendingDeletion()) {
            $container_class .= ' old';
        } elseif ($fact->isPendingAddition()) {
            $container_class .= ' new';
        }

        ob_start();
        echo '<dl><dt class="label">', I18N::translate('Name'), '</dt>';
        echo '<dd class="field">', $dummy->fullName(), '</dd>';
        $ct = preg_match_all('/\n2 (\w+) (.*)/', $fact->gedcom(), $nmatch, PREG_SET_ORDER);
        for ($i = 0; $i < $ct; $i++) {
            $tag = $nmatch[$i][1];
            if ($tag !== 'SOUR' && $tag !== 'NOTE' && $tag !== 'SPFX') {
                echo '<dt class="label">', GedcomTag::getLabel($tag, $individual), '</dt>';
                echo '<dd class="field">'; // Before using dir="auto" on this field, note that Gecko treats this as an inline element but WebKit treats it as a block element
                if (isset($nmatch[$i][2])) {
                    $name = e($nmatch[$i][2]);
                    $name = str_replace('/', '', $name);
                    $name = preg_replace('/(\S*)\*/', '<span class="starredname">\\1</span>', $name);
                    switch ($tag) {
                        case 'TYPE':
                            echo GedcomCodeName::getValue($name, $individual);
                            break;
                        case 'SURN':
                            // The SURN field is not necessarily the surname.
                            // Where it is not a substring of the real surname, show it after the real surname.
                            $surname = e($dummy->getAllNames()[0]['surname']);
                            $surns   = preg_replace('/, */', ' ', $nmatch[$i][2]);
                            if (strpos($dummy->getAllNames()[0]['surname'], $surns) !== false) {
                                echo '<span dir="auto">' . $surname . '</span>';
                            } else {
                                echo I18N::translate('%1$s (%2$s)', '<span dir="auto">' . $surname . '</span>', '<span dir="auto">' . $name . '</span>');
                            }
                            break;
                        default:
                            echo '<span dir="auto">' . $name . '</span>';
                            break;
                    }
                }
                echo '</dd>';
                echo '</dl>';
            }
        }
        if (strpos($fact->gedcom(), "\n2 SOUR") !== false) {
            echo '<div id="indi_sour" class="clearfix">', FunctionsPrintFacts::printFactSources($tree, $fact->gedcom(), 2), '</div>';
        }
        if (strpos($fact->gedcom(), "\n2 NOTE") !== false) {
            echo '<div id="indi_note" class="clearfix">', FunctionsPrint::printFactNotes($tree, $fact->gedcom(), 2), '</div>';
        }
        $content = ob_get_clean();

        if ($fact->canEdit()) {
            $edit_links =
                '<a class="btn btn-link" href="#" data-confirm="' . I18N::translate('Are you sure you want to delete this fact?') . '" onclick="return delete_fact(this.dataset.confirm, \'' . e($individual->tree()->name()) . '\', \'' . e($individual->xref()) . '\', \'' . $fact->id() . '\');" title="' . I18N::translate('Delete this name') . '">' . view('icons/delete') . '<span class="sr-only">' . I18N::translate('Delete this name') . '</span></a>' .
                '<a class="btn btn-link" href="' . e(route('edit-name', ['xref' => $individual->xref(), 'fact_id' => $fact->id(), 'ged' => $individual->tree()->name()])) . '" title="' . I18N::translate('Edit the name') . '">' . view('icons/edit') . '<span class="sr-only">' . I18N::translate('Edit the name') . '</span></a>';
        } else {
            $edit_links = '';
        }

        return '
			<div class="' . $container_class . '">
        <div class="card-header" role="tab" id="name-header-' . $n . '">
		        <a data-toggle="collapse" data-parent="#individual-names" href="#name-content-' . $n . '" aria-expanded="' . $aria . '" aria-controls="name-content-' . $n . '">' . $dummy->fullName() . '</a>
		      ' . $edit_links . '
        </div>
		    <div id="name-content-' . $n . '" class="' . $content_class . '" role="tabpanel" aria-labelledby="name-header-' . $n . '">
		      <div class="card-body">' . $content . '</div>
        </div>
      </div>';
    }
953694
def _write_fact(self, fact_tuple):
        
        fact = self.document.createElement("fact")
        fact.setAttribute('start', fact_tuple.start)
        fact.setAttribute('end', fact_tuple.end)
        fact.setAttribute('activity', fact_tuple.activity)
        fact.setAttribute('duration', fact_tuple.duration)
        fact.setAttribute('category', fact_tuple.category)
        fact.setAttribute('description', fact_tuple.description)
        self.fact_list.appendChild(fact)
513791
public static function formatFactDateShort(\Fisharebest\Webtrees\Fact $fact, $anchor=false) {
		$html='';
		$date = $fact->getDate();
		if($date->isOK()){
			$html.=' '.$date->Display($anchor && !Globals::isSearchSpider(), '%Y');
		}
		else{
			// 1 DEAT Y with no DATE => print YES
			// 1 BIRT 2 SOUR @S1@ => print YES
			// 1 DEAT N is not allowed
			// It is not proper GEDCOM form to use a N(o) value with an event tag to infer that it did not happen.
			$factdetail = explode(' ', trim($fact->getGedcom()));
			if (isset($factdetail) && (count($factdetail) == 3 && strtoupper($factdetail[2]) == 'Y') || (count($factdetail) == 4 && $factdetail[2] == 'SOUR')) {
				$html.=I18N::translate('yes');
			}
		}
		return $html;
	}
723646
function(facts) {
        var ttl = '', fact,
            that = this;
        for (var i = 0; i < facts.length; i++) {
            fact = facts[i];
            ttl += that.factToTurtle(fact);
        }
        return ttl;
    }
377754
public function pastableFactsOfType(GedcomRecord $record, Collection $types): Collection
    {
        // The facts are stored in the session.
        return (new Collection(Session::get('clipboard', [])))
            ->flatten(1)
            ->reverse()
            ->map(static function (array $clipping) use ($record): Fact {
                return new Fact($clipping['factrec'], $record, md5($clipping['factrec']));
            })
            ->filter(static function (Fact $fact) use ($types): bool {
                return $types->contains($fact->getTag());
            });
    }