# Egyedi ellenőrzés a gform_validation szűrővel

> Lépésről lépésre: hogyan írj saját ellenőrzést egy mezőhöz a gform_validation szűrővel, többoldalas űrlapokat és feltételesen rejtett mezőket is kezelve.

Ez a fejezet egy példán mutatja be, hogyan írhatsz saját ellenőrzést a Gravity Forms `gform_validation` szűrőjével. A kód a téma `functions.php` fájljába kerül; a lehetséges helyekről a [Hová tedd a kódrészleteket?](https://hub.hellowp.io/hu/plugins/gravityforms/hogyan-hova-keruljon-a-kod/) fejezet szól.

## A példa

Egy autós weboldalon az űrlapon a látogatók regisztrálhatják a saját autójukat, és az egyik mező a jármű alvázszáma (VIN). Hogyan győződhetsz meg róla, hogy érvényes alvázszámot adtak meg? A `gform_validation` szűrővel.

## A szűrő hozzákapcsolása

```php
// 1 - A saját ellenőrző függvényünk hozzákapcsolása a 'gform_validation' szűrőhöz
add_filter( 'gform_validation_9', 'validate_vin' );
```

Ez a sor azt mondja a Gravity Formsnak, hogy az űrlap beküldésének ellenőrzésekor a saját `validate_vin` függvényünket is futtassa. Mivel ez szűrő és nem művelet, az ellenőrzés eredményét módosíthatjuk, és a feldolgozás a módosításokkal folytatódik.

A szűrő nevének végén a `9` azt jelenti, hogy a függvény csak a 9-es azonosítójú űrlapnál fut le. Nincs értelme minden űrlap beküldésekor futtatni, ha csak egyre van szükség. A 9-et cseréld a célzott űrlap azonosítójára; a megkereséséről az [Űrlap azonosítójának megkeresése](https://hub.hellowp.io/hu/plugins/gravityforms/hogyan-urlap-azonosito/) fejezet szól.

## Az ellenőrzés eredménye

A Gravity Forms a függvénynek egy tömböt ad át, benne két fontos elemmel:

1. `$validation_result['is_valid']`: `true` vagy `false`, azaz hogy az űrlap megbukott-e a Gravity Forms alapértelmezett ellenőrzésein. A 13. lépésben újra találkozol vele.
2. `$validation_result['form']`: az űrlapobjektum, amely az űrlap összes mezőjét tartalmazza.

```php
// 2 - Az űrlapobjektum kinyerése az ellenőrzés eredményéből
$form = $validation_result['form'];
```

Itt az űrlapobjektumot egy helyi változóba tesszük, hogy könnyebben olvasható és használható legyen.

## A jelenlegi oldal meghatározása

```php
// 3 - Az éppen ellenőrzött oldal száma
$current_page = rgpost( 'gform_source_page_number_' . $form['id'] ) ? rgpost( 'gform_source_page_number_' . $form['id'] ) : 1;
```

Ha nem használsz többoldalas űrlapot, ez a lépés nem érint, de jó tudni, hogyan működik. Többoldalas űrlap oldalának beküldésekor a Gravity Forms további adatokat tesz a `$_POST` tömbbe, köztük a forrásoldal számát (az éppen ellenőrzött oldalt). Ezt az `rgpost` függvénnyel olvassuk ki.

Miért fontos? Ha az ellenőrizendő mező az űrlap 2. oldalán van, a látogató pedig az 1. oldalt küldte be, a mező üres, és az egész űrlap ellenőrzése megbukna, így a látogató nem léphetne a következő oldalra.

## Végiglépés a mezőkön

```php
// 4 - Végiglépés az űrlap mezőin
foreach( $form['fields'] as &$field ) {
```

Az űrlapobjektum tartalmazza a mezők tömbjét. Egy ciklussal egyenként végigmehetünk rajtuk, és feltételekkel eldönthetjük, hogy alvázszám-ellenőrzés kell-e. A ciklusban több helyen szerepel a `continue`: ez azt jelenti, hogy az adott mezővel nem foglalkozunk tovább, és a következőre lépünk.

## A mező keresése CSS-osztály alapján

```php
// 5 - Ha a mezőnek nincs meg a kijelölt CSS-osztálya, kihagyjuk
if ( strpos( $field->cssClass, 'validate-vin' ) === false ) {
    continue;
}
```

A példában a mező CSS-osztály tulajdonságát vizsgáljuk. Ugyanígy ellenőrizhetnénk a mező azonosítóját vagy bármely más tulajdonságát, de a CSS-osztály felhasználóbarát módja a saját ellenőrzés gyors hozzáadásának a legtöbb mezőhöz. Az azonosító alapú ellenőrzésnek az a hátránya, hogy ha eltávolítod a mezőt, és az ellenőrzést másik mezőre akarod tenni, a kódot is módosítani kell. A CSS-osztállyal elég az űrlapszerkesztőben a kijelölt osztályt hozzáadnod az új mezőhöz. A példában az osztály neve `validate-vin`.

## A mező oldalszáma

```php
// 6 - A mező oldalszáma
$field_page = $field->pageNumber;
```

Ez a lépés is többoldalas űrlapra vonatkozik. Minden mezőnek van `pageNumber` tulajdonsága, amely azt az oldalt tárolja, amelyen a mező megjelenik. A 8. lépésben használjuk.

## Rejtett-e a mező?

```php
// 7 - Ellenőrzés, hogy a mezőt elrejtette-e a feltételes logika
$is_hidden = RGFormsModel::is_field_hidden( $form, $field, array() );
```

Fontos tudni, hogy a mezőt elrejtette-e a feltételes logika: a rejtett mezőket nem kell ellenőrizni, mert nem részei a beküldésnek. A `RGFormsModel::is_field_hidden()` függvénynek csak egy űrlapobjektum és egy mező kell.

## Kihagyás

```php
// 8 - Ha a mező nincs az aktuális oldalon VAGY rejtett, kihagyjuk
if ( $field_page != $current_page || $is_hidden ) {
    continue;
}
```

Az előző két lépés információt gyűjtött a mezőről. Ha a mező nem az aktuális oldalon van, vagy rejtett, nem futtatjuk rá az alvázszám-ellenőrzést, hanem a ciklus következő mezőjére lépünk.

## A beküldött érték kiolvasása és ellenőrzése

```php
// 9 - A beküldött érték kiolvasása a $_POST tömbből
$field_value = rgpost( "input_{$field['id']}" );

// 10 - Hívás a saját ellenőrző függvényre
$is_valid = is_vin( $field_value );
```

Ha a mező idáig eljut, akkor megvan rajta a kijelölt CSS-osztály, az aktuális oldalon van, és nem rejtett. Most kiolvashatjuk a beküldött értéket az `rgpost` függvénnyel (ez a `$_POST` értékeinek tiszta kiolvasása). A függvénynek átadott karakterlánc például `input_48` lenne, ha nem a mező azonosítójából állítanánk elő.

Ez a kiolvasási mód a legtöbb mezőnél működik. Ismert kivétel a jelölőnégyzetek csoportja és a több bemenetű mezők.

Ezután az `$is_valid` változóba kerül az alvázszám-ellenőrző függvény eredménye: az `is_vin()` megkapja a mező értékét, és igaz vagy hamis értéket ad vissza.

## Érvényes érték

```php
// 11 - Ha érvényes, nincs teendő
if ( $is_valid ) {
    continue;
}
```

Ha a beküldött érték érvényes, nem kell módosítani a mező ellenőrzési tulajdonságait. Ha csak egy mezőt ellenőrzöl alvázszámra (valószínűleg így van), itt technikailag megállhatnál, és visszaadhatnád a változatlan eredményt. A példa azonban több mezőt feltételez, ezért a kód kihagyja a mező további részét, és a ciklus elejére, a következő mezőre lép.

## Sikertelen ellenőrzés

Ha a következő alvázszám-mező ellenőrzése bukik, ezt kell tenni:

```php
// 12 - A mező megbukott: először az egész űrlap ellenőrzését megbuktatjuk
$validation_result['is_valid'] = false;

// 13 - Megjelöljük a mezőt, és egyedi hibaüzenetet adunk
$field->failed_validation = true;
$field->validation_message = 'Az alvázszám, amit megadtál, nem érvényes.';
```

Mivel az űrlapon ellenőrzési hiba van, az `is_valid` értéke `false` lesz. A módosított eredmény visszaadásakor a Gravity Forms ebből tudja, hogy az egyes mezők hibáit is keresnie kell. Ezután a mező `failed_validation` tulajdonsága `true` lesz, a `validation_message` pedig a látogatónak szóló hibaüzenetet adja.

## A módosított űrlap visszaadása az eredménybe

```php
// 14 - A módosított űrlapobjektum visszaírása az eredménybe
$validation_result['form'] = $form;
```

Ez a lépés nagyon fontos. Ha az űrlapobjektumot nem írod vissza a `$validation_result` `form` tulajdonságába, a Gravity Forms nem tudja, melyik mezőnél volt a hiba.

## Az eredmény visszaadása

```php
// 15 - Az eredmény visszaadása
return $validation_result;
```

Végül a módosított (hiba nélkül a változatlan) eredményt visszaadjuk a Gravity Formsnak. Ha egy mező megbukott, a Gravity Forms megakadályozza az űrlap sikeres beküldését, és minden hibás mezőt megjelöl a hozzá tartozó hibaüzenettel.

## A teljes kód

```php
add_filter( 'gform_validation_9', 'validate_vin' );

function validate_vin( $validation_result ) {
    // 2 - Az űrlapobjektum kinyerése az ellenőrzés eredményéből
    $form = $validation_result['form'];

    // 3 - Az éppen ellenőrzött oldal száma
    $current_page = rgpost( 'gform_source_page_number_' . $form['id'] ) ? rgpost( 'gform_source_page_number_' . $form['id'] ) : 1;

    // 4 - Végiglépés az űrlap mezőin
    foreach( $form['fields'] as &$field ) {

        // 5 - Ha a mezőnek nincs meg a kijelölt CSS-osztálya, kihagyjuk
        if ( strpos( $field->cssClass, 'validate-vin' ) === false ) {
            continue;
        }

        // 6 - A mező oldalszáma
        $field_page = $field->pageNumber;

        // 7 - Elrejtette-e a mezőt a feltételes logika
        $is_hidden = RGFormsModel::is_field_hidden( $form, $field, array() );

        // 8 - Ha a mező nem az aktuális oldalon van, vagy rejtett, kihagyjuk
        if ( $field_page != $current_page || $is_hidden ) {
            continue;
        }

        // 9 - A beküldött érték kiolvasása a $_POST tömbből
        $field_value = rgpost( "input_{$field['id']}" );

        // 10 - Hívás a saját ellenőrző függvényre
        $is_valid = is_vin( $field_value );

        // 11 - Ha érvényes, nincs teendő
        if ( $is_valid ) {
            continue;
        }

        // 12 - A mező megbukott: az egész űrlap ellenőrzését megbuktatjuk
        $validation_result['is_valid'] = false;

        // 13 - Megjelöljük a mezőt, és egyedi hibaüzenetet adunk
        $field->failed_validation = true;
        $field->validation_message = 'Az alvázszám, amit megadtál, nem érvényes.';
    }

    // 14 - A módosított űrlapobjektum visszaírása az eredménybe
    $validation_result['form'] = $form;

    // 15 - Az eredmény visszaadása
    return $validation_result;
}

// Kipróbáláshoz egy helyettesítő is_vin függvény
function is_vin( $vin ) {
    // Kipróbáláshoz akkor ad igazat, ha az érték pontosan 17 karakter hosszú.
    // Ez csak példa, nem valódi alvázszám-ellenőrzés.
    return strlen( $vin ) === 17;
}
```
