Yritys "Karjalainen kehittäjä" esittelee päivityksen 0.3.0 "Šuja" sisällönhallintajärjestelmälle "GIRVAS". Versio vaihtaa koodivaiheen "Voitsy" ja saa nimensä Šuja-joen mukaan — yhden Karjalan tasavallan suurimmista joista, joka saa alkunsa Suojärvestä ja laskee Äänisjärveen. Perinne antaa CMS-versioille karjalaisten vesistöjen nimiä korostaa tuotteen alueellista kuuluvuutta ja sen integroitumista kotimaisten teknologisten kehityshankkeiden maisemaan.
Tämä julkaisu keskittyy sisältönavigointityökalujen, hakumahdollisuuksien ja hakukoneoptimointityökalujen kehittämiseen sekä sisältää merkittäviä teknisiä parannuksia järjestelmän ytimeen.
Sisäänrakennettu hakujärjestelmä

Yksi version keskeisistä uudistuksista on täyden tekstin hakujärjestelmän toteutus, joka toimii ilman kolmannen osapuolen palveluita tai liitännäisiä.
Haku suoritetaan merkintöjen otsikoissa, kuvauksissa, pääsisällössä ja avainsanoissa. Toteutettu AND-hakulogiikka, joka jakaa kyselyn automaattisesti yksittäisiin sanoihin ja poistaa välimerkit, mikä mahdollistaa relevanttien materiaalien löytämisen jopa epätarkoilla muotoiluilla. Tulosten relevanssijärjestys perustuu säädettäviin painokertoimiin: osumat otsikoissa ovat etusijalla osumiin verrattuna dokumentin rungossa.
Hallintapaneelissa hakumahdollisuuksia laajennetaan tulevissa päivityksissä: kirjautuneet käyttäjät voivat hakea merkintöjä, staattisia sivuja ja järjestelmän käyttäjiä.
Merkintöjen arkisto päivämääränavigoinnilla
Versio 0.3.0 esittelee sisäänrakennetun merkintöjen arkiston — työkalun kronologiseen sisällön navigointiin.
Toiminto ryhmittelee merkinnät automaattisesti vuosien ja kuukausien mukaan näyttäen julkaisujen määrän kullekin aikavälille. Navigointi tukee suodatusta kategorioittain: käyttäjä voi tarkastella sekä koko sivuston yleisarkistoa että yksittäisen kategorian arkistoa. Leivänmurut muodostuvat dynaamisesti valitun ajanjakson ja kategorian mukaan, mikä mahdollistaa kätevän liikkumisen arkiston tasojen välillä. Arkistosivut on optimoitu hakukoneille — metatunnisteet muodostuvat automaattisesti ja arkistosivujen URL-osoitteet on sisällytetty dynaamiseen sivustokarttaan (sitemap).
Kategorioiden hierarkia ja parannettu navigointi

Päivityksessä on toteutettu tuki alikategorioille rekursiivisella puun läpikäynnillä. Kategoriasivu näyttää nyt merkinnät ottaen huomioon kaikki sisäkkäiset alikategoriat, mikä tarjoaa kattavamman käsityksen sisällöstä.
Leivänmurut kategoria- ja merkintäsivuilla näyttävät täyden hierarkiaketjun juurikategoriasta nykyiseen sijaintiin. Tämä parannus parantaa sekä käyttäjien navigointia että sivuston sisäistä linkitystä hakukoneita varten.
Sisäänrakennettu SEO-sisällönanalyysi

Hallintapaneelin sivu- ja merkintäeditoriin on integroitu asiakaspuolen SEO-analyysi, joka toimii ilman palvelinkutsuja.
Analyysi suorittaa tarkistuksen viidellä osa-alueella: otsikko, meta-kuvaus, avainsanat, sisältö ja URL. Tarkistettavia parametreja ovat SEO-tunnisteiden pituus ja sisältö, avainsanojen esiintyminen otsikoissa, ensimmäisessä kappaleessa ja päätekstissä, otsikkohierarkian oikeellisuus, kuvien alt-tekstin olemassaolo, ulkoisten linkkien rel="nofollow"-attribuutti, "paljaiden" URL-osoitteiden tunnistaminen ja suositukset niiden muotoilemiseksi Markdown-muodossa. Analyysin tulokset näkyvät välittömästi värikoodauksella, edistymispalkeilla ja konkreettisilla parannussuosituksilla.

Sisältölohkot

Hallintapaneeliin on lisätty uusi osio "Sisältölohkot", joka on tarkoitettu erikoiselementtien hallintaan, jotka upotetaan teemojen osioihin ilman mallien muokkausta.
Useita lohkotyyppejä tuetaan:
- "Personoitu" — mielivaltainen sisältö Markdown-muotoilulla;
- "Kabinetti" — käyttäjän miniprofiili, joka näyttää automaattisesti kirjautumislomakkeen kirjautumattomille vierailijoille;
- "Kategorialuettelo" — hierarkkinen luettelo kaikista merkintäkategorioista;
- "Tyhjä" — erikoistunut tyyppi kolmansien osapuolien moduulien integrointia varten.
Jokaiselle lohkolle määritetään näyttösäännöt säännöllisillä lausekkeilla, joita sovelletaan URL-osoitteeseen. Kun pyydetty osoite vastaa mallia, lohko näytetään teeman vastaavassa osiossa.
Tekniset parannukset ytimeen
Versio 0.3.0 sisältää merkittäviä parannuksia QueryBuilder-komponenttiin — sisäiseen SQL-kyselyiden rakentajaan:
- Lisätty tuki JOIN-lauseille (INNER, LEFT, RIGHT, FULL) adaptiivisella ehtojen generoinnilla MySQL:lle ja PostgreSQL:lle;
- Toteutettu CaseExpression-luokka CASE-lausekkeiden rakentamiseen, mukaan lukien erikoistuneet menetelmät JSON-hakuun;
- Lisätty kattava indeksien tuki: luonti ja poisto ottaen huomioon tyypit
BTREE,HASH,GIST,GIN,SPGIST,BRIN,FULLTEXTsekäUNIQUE,CONCURRENTLY,IF NOT EXISTSja osittaiset indeksit WHERE-ehdoilla.
CMS:n asennuksen yhteydessä luodaan nyt automaattisesti optimoivat indeksit kaikille tauluille, mukaan lukien GIN-indeksit JSONB-kentille (PostgreSQL) ja osittainen indeksi julkaistuille merkinnöille. Indeksien luontivirheet kirjataan lokiin keskeyttämättä asennusprosessia.
EntryCategory-luokkaan on lisätty alustettujen tietojen välimuistitus, joka estää toistuvat tietokantakyselyt initData()-metodin useissa kutsuissa.
Migraatio
Tiedostojärjestelmän päivitys
Suosittelemme vahvasti päivityksen hakemista CMS "GIRVAS" -virallisesta arkistosta. Jos käytät sitä oletuksena, suorita projektisi juuressa konsolikomento git pull vaihdettuasi aiemmin production-haaralle (jos olet aiemmin käyttänyt toista haaraa).
Tiedostojärjestelmän päivityksen jälkeen tyhjennä välimuisti: rm -R ./cache/* (polku voi vaihdella riippuen todellisesta sijainnistasi järjestelmässä).
Tietokannan migraatio
CMS-tiedostojen onnistuneen päivityksen jälkeen on suoritettava tietokannan migraatio. Tätä varten on suoritettava useita SQL-kyselyjä tietokannallesi (voit vain kopioida ja liittää) riippuen tietokannan tyypistä.
MySQL:lle
-- Sisältölohkojen taulun luonti --
CREATE TABLE IF NOT EXISTS content_blocks (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
name TEXT NOT NULL,
texts JSON,
metadata JSON,
createdUnixTimestamp INTEGER NOT NULL DEFAULT 0,
updatedUnixTimestamp INTEGER NOT NULL DEFAULT 0
);
-- Indeksit entries-taululle
CREATE INDEX idx_entries_category ON entries (categoryID);
CREATE INDEX idx_entries_author ON entries (authorID);
CREATE INDEX idx_entries_created ON entries (createdUnixTimestamp DESC);
CREATE INDEX idx_entries_updated ON entries (updatedUnixTimestamp);
CREATE UNIQUE INDEX idx_entries_name_unique ON entries (name);
-- Indeksit entries_categories-taululle
CREATE INDEX idx_entries_categories_parent ON entries_categories (parentID);
CREATE UNIQUE INDEX idx_entries_categories_name_unique ON entries_categories (name);
-- Indeksit entries_comments-taululle
CREATE INDEX idx_entries_comments_entry ON entries_comments (entryID);
CREATE INDEX idx_entries_comments_author ON entries_comments (authorID);
CREATE INDEX idx_entries_comments_created ON entries_comments (createdUnixTimestamp DESC);
-- Indeksit pages_static-taululle
CREATE UNIQUE INDEX idx_pages_static_name_unique ON pages_static (name);
CREATE INDEX idx_pages_static_author ON pages_static (authorID);
CREATE INDEX idx_pages_static_created ON pages_static (createdUnixTimestamp DESC);
-- Indeksit users-taululle
CREATE UNIQUE INDEX idx_users_login_unique ON users (login);
CREATE UNIQUE INDEX idx_users_email_unique ON users (email);
-- Indeksit users_sessions-taululle
CREATE INDEX idx_users_sessions_user ON users_sessions (userID);
CREATE INDEX idx_users_sessions_token ON users_sessions (token);
-- Indeksit forms_data-taululle
CREATE INDEX idx_forms_data_form ON forms_data (formID);
CREATE INDEX idx_forms_data_created ON forms_data (createdUnixTimestamp DESC);
-- Indeksit web_channels-taululle
CREATE UNIQUE INDEX idx_web_channels_name_unique ON web_channels (name);
-- Indeksit metrics-taululle
CREATE INDEX idx_metrics_date ON metrics (date);
PostgreSQL:lle
-- Sisältölohkojen taulun luonti --
CREATE TABLE IF NOT EXISTS content_blocks (
"id" SERIAL NOT NULL PRIMARY KEY,
"name" TEXT NOT NULL,
"texts" JSONB,
"metadata" JSONB,
"createdUnixTimestamp" INTEGER NOT NULL DEFAULT 0,
"updatedUnixTimestamp" INTEGER NOT NULL DEFAULT 0
);
-- Indeksit entries-taululle
CREATE INDEX IF NOT EXISTS idx_entries_category ON entries ("categoryID");
CREATE INDEX IF NOT EXISTS idx_entries_author ON entries ("authorID");
CREATE INDEX IF NOT EXISTS idx_entries_created ON entries ("createdUnixTimestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_entries_updated ON entries ("updatedUnixTimestamp");
CREATE UNIQUE INDEX IF NOT EXISTS idx_entries_name_unique ON entries ("name");
CREATE INDEX IF NOT EXISTS idx_entries_texts_gin ON entries USING GIN (texts);
CREATE INDEX IF NOT EXISTS idx_entries_metadata_gin ON entries USING GIN (metadata);
CREATE INDEX IF NOT EXISTS idx_entries_published ON entries ("createdUnixTimestamp" DESC) WHERE (metadata::jsonb->>"isPublished")::boolean = true;
-- Indeksit entries_categories-taululle
CREATE INDEX IF NOT EXISTS idx_entries_categories_parent ON entries_categories ("parentID");
CREATE UNIQUE INDEX IF NOT EXISTS idx_entries_categories_name_unique ON entries_categories ("name");
-- Indeksit entries_comments-taululle
CREATE INDEX IF NOT EXISTS idx_entries_comments_entry ON entries_comments ("entryID");
CREATE INDEX IF NOT EXISTS idx_entries_comments_author ON entries_comments ("authorID");
CREATE INDEX IF NOT EXISTS idx_entries_comments_created ON entries_comments ("createdUnixTimestamp" DESC);
-- Indeksit pages_static-taululle
CREATE UNIQUE INDEX IF NOT EXISTS idx_pages_static_name_unique ON pages_static ("name");
CREATE INDEX IF NOT EXISTS idx_pages_static_author ON pages_static ("authorID");
CREATE INDEX IF NOT EXISTS idx_pages_static_created ON pages_static ("createdUnixTimestamp" DESC);
CREATE INDEX IF NOT EXISTS idx_pages_static_texts_gin ON pages_static USING GIN (texts);
-- Indeksit users-taululle
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_login_unique ON users ("login");
CREATE UNIQUE INDEX IF NOT EXISTS idx_users_email_unique ON users ("email");
-- Indeksit users_sessions-taululle
CREATE INDEX IF NOT EXISTS idx_users_sessions_user ON users_sessions ("userID");
CREATE INDEX IF NOT EXISTS idx_users_sessions_token ON users_sessions ("token");
-- Indeksit forms_data-taululle
CREATE INDEX IF NOT EXISTS idx_forms_data_form ON forms_data ("formID");
CREATE INDEX IF NOT EXISTS idx_forms_data_created ON forms_data ("createdUnixTimestamp" DESC);
-- Indeksit web_channels-taululle
CREATE UNIQUE INDEX IF NOT EXISTS idx_web_channels_name_unique ON web_channels ("name");
-- Indeksit metrics-taululle
CREATE INDEX IF NOT EXISTS idx_metrics_date ON metrics ("date");
Päätelmä
CMS "GIRVAS" -päivitys 0.3.0 "Šuja" yhdistää käyttäjien navigointi- ja hakutyökalujen kehityksen ytimen syvälliseen tekniseen modernisointiin. Suosittelemme kaikkia käyttäjiä suorittamaan päivityksen arvioidakseen parantuneita hakumahdollisuuksia, sisällön arkistoinnin kätevyyttä ja uusia hakukoneoptimointityökaluja.
Kommentit