Print a row for the notes tab on the individual page.

@param Fact $fact
@param int  $level

@return void
426644
public static function printMainNotes(Fact $fact, int $level): void
    {
        $factrec = $fact->gedcom();
        $parent  = $fact->record();
        $tree    = $parent->tree();

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

        $ct = preg_match_all("/$level NOTE (.*)/", $factrec, $match, PREG_SET_ORDER);
        for ($j = 0; $j < $ct; $j++) {
            // Note object, or inline note?
            if (preg_match("/$level NOTE @(.*)@/", $match[$j][0], $nmatch)) {
                $note = Note::getInstance($nmatch[1], $tree);
                if ($note && !$note->canShow()) {
                    continue;
                }
            } else {
                $note = null;
            }

            if ($level >= 2) {
                echo '<tr class="wt-level-two-note collapse"><th scope="row" class="rela ', $styleadd, '">';
            } else {
                echo '<tr><th scope="row" class="', $styleadd, '">';
            }
            if ($can_edit) {
                if ($level < 2) {
                    if ($note instanceof Note) {
                        echo '<a href="' . e($note->url()) . '">';
                        echo GedcomTag::getLabel('SHARED_NOTE');
                        echo view('icons/note');
                        echo '</a>';
                    } else {
                        echo GedcomTag::getLabel('NOTE');
                    }
                    echo '<div class="editfacts">';
                    echo view('edit/icon-fact-edit', ['fact' => $fact]);
                    echo view('edit/icon-fact-copy', ['fact' => $fact]);
                    echo view('edit/icon-fact-delete', ['fact' => $fact]);
                    echo '</div>';
                }
            } else {
                if ($level < 2) {
                    if ($tree->getPreference('SHOW_FACT_ICONS')) {
                        echo '<i class="icon-note"></i> ';
                    }
                    if ($note) {
                        echo GedcomTag::getLabel('SHARED_NOTE');
                    } else {
                        echo GedcomTag::getLabel('NOTE');
                    }
                }
                $factlines = explode("\n", $factrec); // 1 BIRT Y\n2 NOTE ...
                $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 ($factname !== 'NOTE') {
                    // Note is already printed
                    echo GedcomTag::getLabel($factname, $parent);
                    if ($note) {
                        echo '<a class="btn btn-link" href="' . e($note->url()) . '" title="' . I18N::translate('View') . '"><span class="sr-only">' . I18N::translate('View') . '</span></a>';
                    }
                }
            }
            echo '</th>';
            if ($note) {
                // Note objects
                $text = Filter::formatText($note->getNote(), $tree);
            } else {
                // Inline notes
                $nrec = Functions::getSubRecord($level, "$level NOTE", $factrec, $j + 1);
                $text = $match[$j][1] . Functions::getCont($level + 1, $nrec);
                $text = Filter::formatText($text, $tree);
            }

            echo '<td class="optionbox', $styleadd, ' wrap">';
            echo $text;

            // 2 RESN tags. Note, there can be more than one, such as "privacy" and "locked"
            if (preg_match_all("/\n2 RESN (.+)/", $factrec, $matches)) {
                foreach ($matches[1] as $match) {
                    echo '<br><span class="label">', GedcomTag::getLabel('RESN'), ':</span> <span class="field">';
                    switch ($match) {
                        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 $match;
                            break;
                    }
                    echo '</span>';
                }
            }
            echo '</td></tr>';
        }
    }
1286111
public function log($msg, $runlevel = self::LEVEL_INFO) {
		$time = time();
		#$this->data[] = array($this->runlevel, $msg, $time);
		if($this->printout and $runlevel <= $this->runlevel) {
			$this->writeLine($msg, $runlevel, $time);
		}
	}
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;
	}
1243561
public function write(string $level, string $message, array $context)
    {
        $this->logger->log($level, $message, $context);
    }
660282
public function log($level, $message, array $context = array())
    {
        $message = $this->formatMessage($level, $message, $context);        
        $this->write($message);
    }
1237869
public function write_record($record, $rownum) {
        echo \html_writer::start_tag('tr');
        foreach ($record as $cell) {
            echo \html_writer::tag('td', $cell);
        }
        echo \html_writer::end_tag('tr');
    }
346297
private static function debug_print($file, $level, $format, $data)
    {
        array_shift($data);
        foreach ($data as $k => $v) {
            if (is_string($v)) {
                $data[$k] = str_replace("\n", ' ', $v);
            } elseif ($v instanceof \Exception) {
                $data[$k] = $v->__toString();
            } elseif (!is_numeric($v)) {
                $data[$k] = str_replace("\n", " ", json_encode($v));
            }
        }

        $mtime = microtime(true);
        $time = 1000 * ($mtime - intval($mtime));

        $trace = debug_backtrace();
        $location = $trace[2]['function'];
        for ($n = 2; $n < sizeof($trace); $n++) {
            if (isset($trace[$n]['class'])) {
                $location = $trace[$n]['class'];
                break;
            }
        }

        $id = isset($_SERVER['REMOTE_PORT']) ? $_SERVER['REMOTE_PORT'] : getmypid();

        $msg = sizeof($data) ? vsprintf($format, $data) : $format;
        error_log(sprintf("[%s.%03d %s %s %s] %s\n", date('d.m.Y H:m:s'), $time, $id, $level, $location, $msg), 3, $file);
    }
349357
private function _toFormatTree($list, $level = 0)
    {
        $formatTree = [];
        foreach ($list as $val) {
            $tmp_str = str_repeat($this->tabSize, $level);
            $tmp_str .= "└&nbsp;";
            
            $val['level'] = intval($level);
            $val[$this->showTitleField] = $level == 0 ? $val[$this->showTitleField] : $tmp_str . $val[$this->showTitleField];
            if (!array_key_exists('_child', $val)) {
                array_push($formatTree, $val);
            } else {
                $tmp_ary = $val['_child'];
                unset($val['_child']);
                array_push($formatTree, $val);
                $formatTree = array_merge($formatTree, $this->_toFormatTree($tmp_ary, $level + 1));
            }
        }
        
        return $formatTree;
    }
180309
public function deleteFact(string $fact_id, bool $update_chan): void
    {
        $this->updateFact($fact_id, '', $update_chan);
    }
1116497
protected function write($object, $level)
    {
        if ($this->enabled && $this->writer && $level <= $this->level) {
            return $this->writer->write($object, $level);
        } else {
            return false;
        }
    }
395018
public static function isNull( $fact )
	{
		if ( ! $fact instanceof DOMXPathNavigator )
		{
			throw new \Exception( "Invalid fact variable passed to FactValues::isNull" );
		}

		if ( ! $fact->getHasAttributes() ) return false;

		$attributes = $fact->CloneInstance();
		return $attributes->MoveToAttribute( "nil", \XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_SCHEMA_INSTANCE ] );
	}
166247
public function tLog(string $level, string $message, array $context = []) {
        $logtag = $this->getLogTag();
        if (is_array($message) || is_object($message)) {
            $message = print_r($message, true);
        }
        $this->log($level, "[{time}] [{$logtag}] ".$message, $context);
    }
1173729
static function record($message,$level=self::ERR,$record=false) {
        if($record || false !== strpos(C('LOG_LEVEL'),$level)) {
            self::$log[] =   "{$level}: {$message}\r\n";
        }
    }
1344946
private function getFactDetails( $variableSet, $types, $fact )
	{
		$factHash = spl_object_hash( $fact );

		if ( ! isset( $this->factCache[ $factHash ] ) )
		{
			// Record the QName and other cache information if not defined
			if ( ! isset( $this->factQNameCache[ $factHash ] ) )
			{
				// Look up the namespace to find the schema prefix
				$factNamespace = $fact->getNamespaceURI();
				if ( ! isset( $this->factNamespaceCache[ $factNamespace ] ) )
				{
					$factTaxonomy = $variableSet->xbrlTaxonomy->getTaxonomyForNamespace( $fact->getNamespaceURI() );
					// Record the mapping
					$this->factNamespaceCache[ $factNamespace ] = $factTaxonomy->getPrefix();
				}
				// Retrieve the prefix to create a QName
				$factPrefix = $this->factNamespaceCache[ $factNamespace ];
				$factQName = new QName( $factPrefix, $fact->getNamespaceURI(), $fact->getLocalName() );

				// And record it against the fact hash
				$this->factQNameCache[ $factHash ] = $factQName;
				// If there is no element cached for the QName get it can record it
				if ( ! isset( $this->factElementCache[ $factQName->clarkNotation() ] ) )
				{
					$this->factElementCache[ $factQName->clarkNotation() ] = $types->getElement( $factQName->localName, $factQName->prefix );
				}
			}

			$factQName = $this->factQNameCache[ $factHash ];

			if ( ! isset( $this->factComponentsCache[ $factHash ] ) )
			{
				$this->factComponentsCache[ $factHash ] = $this->getFactComponents( $variableSet, $fact );
			}

			$factComponents = $this->factComponentsCache[ $factHash ];
			$factComponents['factHash'] = $factHash;
			$factComponents['qname'] = $factQName;
			$factComponents['fact'] = $fact;

			$this->factCache[ $factHash ] = $factComponents;
		}

		return $this->factCache[ $factHash ];
	}
839749
public function log($level, $message, array $context = [])
    {
        $record = new LogRecord($level, $message);

        // add all messages to session log
        $this->session->addRecord($record);

        // write record into log only if it is enough by level
        if ($this->logLevel >= $level) {
            $this->write($record);
        }
    }
194863
public function writeError($line, $check, $message, $level = WARNING) {

		// Update the counters
		$this->nbErrors ++;
		$this->fileErrors ++;
		if ($this->fileInError === false) {
			$this->nbfilesError ++;
			$this->fileInError = true;
		}

		// Add the check to the details
		$detail = $this->_readTemplate("detail_body");
		$values = array();
		$values['%%message%%'] = htmlspecialchars($message);
		$values['%%check%%'] = $check;
		$values['%%line%%'] = $line;
		$values['%%level%%'] = $level;
		$detail = $this->_fillTemplate($detail, $values);
		$this->fileDetail .= $detail;
	}
389432
protected function write($level, $msg)
    {
        $time = date('Y-m-d H:i:s', time());
        $msg = "[" . $time . "][" . static::getLevelName($level) . "] " . $msg . PHP_EOL;

        if($this->debugOutput === true){
            echo $msg;
        }
        if (static::$silent) {
            return false;
        }
        if (!$this->isAllowed($level)) {
            return false;
        }
        $fh = fopen($this->logFile, 'a');
        if (!fwrite($fh, $msg)) {
            throw new \Exception('Failed to write to log file at ' . $this->logFile);
        }

        return true;
    }