138 lines
3.7 KiB
PHP
138 lines
3.7 KiB
PHP
<?php
|
||
|
||
namespace App\Entity;
|
||
|
||
class SentenceNote extends Note
|
||
{
|
||
const MODEL_NAME = 'Japanese sentences';
|
||
const DECK = '日本語::音読';
|
||
|
||
private ?array $mediaInfo = [];
|
||
private array $terms = [];
|
||
|
||
// -------------------------------------------------- Getters & setters ---
|
||
|
||
/** @return list<Term> */
|
||
public function getTerms(): array
|
||
{
|
||
return $this->terms;
|
||
}
|
||
/** @param list<Terms> $terms */
|
||
public function setTerms(array $terms): static
|
||
{
|
||
$this->terms = $terms;
|
||
return $this;
|
||
}
|
||
|
||
|
||
// ------------------------------------------------------- Anki-related ---
|
||
|
||
public static function fromAnki(array $noteInfo): static
|
||
{
|
||
$note = parent::fromAnki($noteInfo);
|
||
|
||
if ($note->getModel() !== self::MODEL_NAME) {
|
||
throw new \Exception('Trying to parse wrong model');
|
||
}
|
||
|
||
$note->mediaInfo = Note::parseMediaInfo($note->fields['Notes']);
|
||
|
||
// Set VocabKanji field
|
||
$note->terms = Term::fromNoteFields($note->fields);
|
||
|
||
// If unable to, create them from the highlighted parts in the sentence
|
||
if (empty($note->terms)) {
|
||
foreach ($note->getHighlightedKanji() as $highlighedKanji) {
|
||
$term = new Term();
|
||
$term->kanji = $highlighedKanji;
|
||
$term->definitionEn = null;
|
||
$term->definitionJp = null;
|
||
$note->terms[] = $term;
|
||
}
|
||
}
|
||
|
||
// Set to null whatever is null
|
||
$readings = array_map(
|
||
fn($x) => in_array($x, ['_', '_', '']) ? null : $x,
|
||
explode('|', $note->fields['VocabFurigana']),
|
||
);
|
||
|
||
// Set readings from furigana field
|
||
foreach ($note->terms as $key => &$term) {
|
||
if (null === $term->getReading()) {
|
||
if (null !== ($readings[$key] ?? null)) {
|
||
$term->kanji .= '[' . $readings[$key] . ']';
|
||
}
|
||
}
|
||
}
|
||
|
||
return $note;
|
||
}
|
||
|
||
public function toAnki(): array
|
||
{
|
||
return array_merge(parent::toAnki(), [
|
||
'fields' => [
|
||
'VocabKanji' => join('|', array_map(
|
||
fn(Term $x) => $x->getKanji(),
|
||
$this->terms,
|
||
)),
|
||
'VocabFurigana' => join('|', array_map(
|
||
fn(Term $x) => $x->getReading() ?? '_',
|
||
$this->terms,
|
||
)),
|
||
'VocabDef' => join("<br>\n", array_map(
|
||
fn(Term $x) => $x->toAnkiVocabDef(),
|
||
$this->terms,
|
||
)),
|
||
],
|
||
]);
|
||
}
|
||
|
||
|
||
// ---------------------------------------------------- Derived methods ---
|
||
|
||
public function hasTerm(string $kanji): bool
|
||
{
|
||
foreach ($this->terms as $term) {
|
||
assert($term instanceof Term);
|
||
|
||
if ($term->kanji == $kanji) return true;
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
public function isSentKanjiHighlighted(): bool
|
||
{
|
||
return str_contains(
|
||
$this->fields['SentKanji'],
|
||
self::HIGHLIGHT_ATTR_KANJI,
|
||
);
|
||
}
|
||
|
||
/** Return an array of strings with the highlighted kanji in the SentKanji */
|
||
public function getHighlightedKanji(): array
|
||
{
|
||
$ret = [];
|
||
$matches = [];
|
||
|
||
// 1. Get all spans in the text
|
||
preg_match_all(
|
||
self::HIGHLIGHT_PATTERN,
|
||
$this->fields['SentKanji'],
|
||
$matches,
|
||
PREG_SET_ORDER,
|
||
);
|
||
|
||
// 2. Check the ones that match with the kanji color
|
||
foreach ($matches as $match) {
|
||
if ($match[1] === self::HIGHLIGHT_ATTR_KANJI) {
|
||
$ret[] = mb_trim($match[2]);
|
||
}
|
||
}
|
||
|
||
return $ret;
|
||
}
|
||
}
|