/ Gists / Nette

Gists - Nette

On gists

Ajax dependent selectbox

Nette Nette-Forms

example.php #

<?php
// https://forum.nette.org/cs/27213-dependent-form-select-with-ajax-chyba-please-select-a-valid-option
// https://forum.nette.org/cs/32545-jak-na-vicekrokovy-formular#p207046

protected function createComponentSelectForm($name)
{
    $firstItems = [
        1 => 'First option 1',
        2 => 'First option 2'
    ];

    // Je důležité předávat formuláři $this a $name jinak by nefungovalo níže použité $firstSelect->getValue()
    $form = new \Nette\Application\UI\Form($this, $name);
    $firstSelect = $form->addSelect('first', 'First select:', $firstItems)
        ->setPrompt('Select');

    $secondItems = [0 => 'Select from first'];

    if ($firstSelect->getValue()) {
        $secondItems = [
            0 => 'Select',
            1 => 'First option ' . $value . ' - second option 1',
            2 => 'First option ' . $value . ' - second option 2'
        ];
    }

    $form->addSelect('second', 'Second select:')
         ->setItems($secondItems);

    $form->addSubmit('send', 'Submit');

    $form->onSuccess[] = [$this, 'processSelectForm'];

    return $form;
}

On gists

Multiplier multiple

Nette Nette-Forms

multiplier.php #

<?php

return new Multiplier(function ($id) {
    return new Multiplier(function ($id2) use ($id) {

    });
});

On gists

Neon - konfigurace přes službu a metody

Nette Nette-Neon Nette-Tricks

config.neon #

services:
    - Config
reCaptcha:
    siteKey: @Config::getSiteKey()
    secretKey: @Config::getSecretKey()
    methodName: 'addReCaptcha' # optional

On gists

Dekorator - Response

Nette

decorator-nette.php #

<?php
# https://forum.nette.org/cs/31783-mazanie-suboru-po-samotnej-akcii-stiahnut-subor#p202279

use Nette\Application\Responses\FileResponse;
use Nette\Http\IRequest;
use Nette\Http\IResponse;

final class DownloadAndDeleteFileResponse implements Nette\Application\IResponse
{
    private $response;

    public function __construct(FileResponse $response)
    {
        $this->response = $response;
    }

    public funcion send(IRequest $request, IResponse $response)
    {
        $this->response->send($request, $response);
        unlink($this->response->getFile());
    }

On gists

Jakým tlačítkem byl odeslán formulář? SubmittedBy() ?

Nette Nette-Forms Nette-Tricks

submitted-by.php #

<?php

if ($form['submit']->isSubmittedBy()) {
    // ...
}
or

if ($form->isSubmitted() === $form['submit']) {
    // ...
}

or

public function validate($form)
{
	if ($form->isSubmitted()->getName() == 'reloadSelect')
		return;
}

On gists

Component - Youtube

Nette

youtube.php #

<?php

namespace App\FrontModule\Components;

use App;
use Nette\Application\UI\Control;
use Nette\Caching\Cache;
use Nette\Caching\IStorage;

/**
 * Class Youtube
 */
class Youtube extends FrontControl
{
    public $presets;
    public $content;
    public $cacheStorage;

    public function __construct(App\Model\Presets $presets, IStorage $IStorage)
    {
        $this->presets = $presets;
        $this->cacheStorage = $IStorage;
    }

    private function fetchData()
    {

        $user = $this->presets->defaults['keys']['youtube']['user'];
        $path = "https://www.youtube.com/feeds/videos.xml?channel_id=$user";

        try {
            $out = json_decode(json_encode(@new \SimpleXMLIterator($path, null, true)), TRUE);

            return $out;
        } catch (\Exception $e) {
            return false;
        }
    }


    public function getData()
    {

        $cache = new Cache($this->cacheStorage, 'youtubePosts');

        try {
            $out = $cache->load("videos");
        } catch (\Exception $e) {
            $out = false;
        }

        if (empty($out)) {
            try {
                $data = self::fetchData();

                if ($data) {
                    $out = $data['entry'];
                    $cache->save("videos", $out, array(
                        Cache::EXPIRATION => '+30 minutes',
                        Cache::SLIDING => TRUE
                    ));
                } else {
                    $out = false;
                }

            } catch (\Exception $e) {
                $out = false;
            }
        }
        return $out;

    }


	public function renderDefault(array $config = array())
	{	
        $config = $this->getCurrentConfig($config);
        $this->template->presets = $this->presets->getPresets();
        $this->template->youtubeData = $this->getData();

		$this->render($config);
	}



}

On gists

Component - Instagram

Nette

instagram.php #

<?php

namespace App\FrontModule\Components;

use App;
use Nette\Caching\Cache;
use Nette\Caching\IStorage;
use Nette\Utils\Json;

/**
 * Class Instagram
 */
class Instagram extends FrontControl
{
    public $presets;
    public $content;
    public $cacheStorage;

    public function __construct(App\Model\Presets $presets, IStorage $IStorage)
    {
        $this->presets = $presets;
        $this->cacheStorage = $IStorage;
    }

    private function fetchData()
    {

        $token = $this->presets->defaults['keys']['instagram']['token'];
        $user = $this->presets->defaults['keys']['instagram']['user'];
        $url = "https://api.instagram.com/v1/users/$user/media/recent/?access_token=$token";

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, 20);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }

    public function getData()
    {

        $cache = new Cache($this->cacheStorage, 'instagramPosts');

        try {
            $out = $cache->load("photos");
        } catch (\Exception $e) {
            $out = false;
        }

        if (empty($out)) {
            try {
                $data = self::fetchData();
                $out = Json::decode($data, true);
                $out = $out['data'];
                $cache->save("photos", $out, array(
                    Cache::EXPIRATION => '+30 minutes',
                    Cache::SLIDING => TRUE
                ));
            } catch (\Exception $e) {
                $out = false;
            }
        }
        return $out;

    }

	public function renderDefault(array $config = array())
	{	
        $config = $this->getCurrentConfig($config);
        $this->template->presets = $this->presets->getPresets();
        $this->template->instagramData = $this->getData();

		$this->render($config);
	}


}

On gists

Snippets for Latte (Nette)

Nette

latte.json #

{
    "block": { "prefix": "block", "body": "{block ${1:content}}\n$0\n{/block}" },
    "snippet": { "prefix": "snippet", "body": "{snippet ${1:content}}\n$0\n{/snippet}" },
    "layout": { "prefix": "layout", "body": "{layout '${1:../@layout.latte}'}\n$0" },
    "extends": { "prefix": "extends", "body": "{extends '${1:../@layout.latte}'}\n$0" },
    "capture": { "prefix": "capture", "body": "{capture \\$${1:var}}\n$0\n{/capture}" },
    "define": { "prefix": "define", "body": "{define ${1:content}}\n$0\n{/define}" },
    "include": { "prefix": "include", "body": "{include #${1:content}}\n$0" },
    "includeblock": { "prefix": "includeblock", "body": "{includeblock '${1:file.latte}'}\n$0" },
    "foreach": { "prefix": "foreach", "body": "{foreach \\$$1s as \\$$1}\n$0\n{/foreach}" },
    "while": { "prefix": "while", "body": "{while \\$$1 = \\$$1s->fetch()}\n$0\n{/while}" },
    "for": { "prefix": "for", "body": "{for \\$${1:i} = 0; \\$${1:i} < ${2:10}; \\$${1:i}++}\n$0\n{/for}" },
    "first": { "prefix": "first", "body": "{first}\n$0\n{/first}" },
    "last": { "prefix": "last", "body": "{last}\n$0\n{/last}" },
    "sep": { "prefix": "sep", "body": "{sep}\n$0\n{/sep}" },
    "continueIf": { "prefix": "continueIf", "body": "{continueIf \\$${1:foo}}$0" },
    "breakIf": { "prefix": "breakIf", "body": "{breakIf \\$${1:foo}}$0" },
    "if": { "prefix": "if", "body": "{if \\$${1:foo}}\n$0\n{/if}" },
    "ifset": { "prefix": "ifset", "body": "{ifset \\$${1:foo}}\n$0\n{/ifset}" },
    "cache": { "prefix": "cache", "body": "{cache \\$${1:var}}\n$0\n{/cache}" },
    "default": { "prefix": "default", "body": "{default \\$${1:foo = ''}}$0" },
    "link": { "prefix": "link", "body": "{link ${1:Default}}\n$0" },
    "plink": { "prefix": "plink", "body": "{plink ${1:Default}}\n$0" },
    "control": { "prefix": "control", "body": "{control ${1:foo}}\n$0" },
    "form": { "prefix": "form", "body": "{form ${1:foo}}\n$0\n{/form}" },
    "label": { "prefix": "label", "body": "{label ${1:foo} /}\n" },
    "input": { "prefix": "input", "body": "{input ${1:foo}}\n$0" },
    "syntax": { "prefix": "syntax", "body": "{syntax ${1:mode}}\n$0\n{/syntax}" },
    "l": { "prefix": "l", "body": "{l}$0" },
    "r": { "prefix": "r", "body": "{r}$0" },
    "contentType": { "prefix": "contentType", "body": "{contentType ${1:application/xml}}\n$0" },
    "status": { "prefix": "status", "body": "{status ${1:500}}\n$0" },
    "dump": { "prefix": "dump", "body": "{dump \\$${1:var}}\n$0" },
    "debugbreak": { "prefix": "debugbreak", "body": "{debugbreak \\$${1:cond}}\n$0" },


    // Default Helpers
    // String modification
    "|truncate": { "prefix": "|truncate", "body": "|truncate:${1:length}${2:,'${3:append}'}" },
    "|substr": { "prefix": "|substr", "body": "|substr:${1:offset}${2:,${3:length}}" },
    "|trim": { "prefix": "|trim", "body": "|trim${1::'${2:charset}'}" },
    "|webalize": { "prefix": "|webalize", "body": "|webalize${1::'${2:charlist}'${3:,${4:lower}}}" },
    "|indent": { "prefix": "|indent", "body": "|indent${1::${2:level}${3:,'${4:char}'}}" },
    "|replace": { "prefix": "|replace", "body": "|replace:'${1:search}'${2:,'${3:replace}'}" },
    "|replaceRE": { "prefix": "|replaceRE", "body": "|replaceRE:'${1:pattern}'${2:,'${3:replace}'}" },
    "|padLeft": { "prefix": "|padLeft", "body": "|padLeft:${1:length}${2:,'${3:pad}'}" },
    "|padRight": { "prefix": "|padRight", "body": "|padRight:${1:length}${2:,'${3:pad}'}" },
    "|repeat": { "prefix": "|repeat", "body": "|repeat:${1:count}" },
    "|implode": { "prefix": "|implode", "body": "|implode:'${1:glue}'" },

    // Formatting
    "|date": { "prefix": "|date", "body": "|date:'${1:format}'" },
    "|number": { "prefix": "|number", "body": "|number${1::${2:decimals}${3:,'${4:decPoint}'${5:,'${6:thousandsSep}'}}}" },
    "|bytes": { "prefix": "|bytes", "body": "|bytes${1::${2:precision}}" },  

}

On gists

Form šablona přes bloky

Nette Nette-Forms Nette-Tricks

form.latte #

{define form $formName}
	<form n:name=$formName>
	<ul class=error n:ifcontent>
		<li n:foreach="$form->ownErrors as $error">{$error}</li>
	</ul>

	<table>
	<tr n:foreach="$form->controls as $input"
		n:if="!$input->getOption(rendered) && $input->getOption(type) !== hidden"
		n:class="$input->required ? required">

		<th>{label $input}</th>
		<td>{input $input} <span class=error n:ifcontent>{$input->error}</span></td>
	</tr>
	</table>
	</form>
{/define}


{* for Bootstrap v3 *}
{define bootstrap-form $formName}
	<form n:name=$formName class=form-horizontal>
	<ul class=error n:ifcontent>
		<li n:foreach="$form->ownErrors as $error">{$error}</li>
	</ul>

	<div n:foreach="$form->controls as $name => $input"
		n:if="!$input->getOption(rendered) && $input->getOption(type) !== hidden"
		n:class="form-group, $input->required ? required, $input->error ? has-error">

		<div class="col-sm-2 control-label">{label $input}</div>

		<div class="col-sm-10">
			{if $input->getOption(type) in [text, select, textarea]}
				{input $input class => form-control}
			{elseif $input->getOption(type) === button}
				{input $input class => "btn btn-default"}
			{elseif $input->getOption(type) === checkbox}
				<div class="checkbox">{input $input}</div>
			{elseif $input->getOption(type) === radio}
				<div class="radio">{input $input}</div>
			{else}
				{input $input}
			{/if}

			<span class=help-block n:ifcontent>{$input->error ?: $input->getOption(description)}</span>
		</div>
	</div>
	</form>
{/define}

On gists

Nette own storage via Session - wrapper

Nette PHP

Storage.php #

<?php

namespace Model;

use Nette;

class DemandStorage extends Nette\Object
{
    protected $session;
    public function __construct(Nette\Http\Session $session)
    {
        $this->session = $session->getSection('demandForm');    
    }

    public function flush()
    {
        $this->session->remove();
    }

    public function getRawData()
    {
        return isset($this->session['formData']) ? $this->session['formData'] : array();
    }

    public function getStepNumber()
    {
        return isset($this->session['step']) ? $this->session['step'] : 1;
    }

    public function setRawData($data)
    {
        $this->session['formData'] = $data;
        return $this;
    }

    public function addRawData($data)
    {
        $originalData = $this->getRawData();
        $data = array_merge($originalData, $data);
        $this->setRawData($data);
        return $this;
    }

    public function setStepNumber($step = 1)
    {
        $this->session['step'] = $step;
        return $this;
    }

    public function getValue($name, $default = NULL)
    {
        $data = $this->getRawData();
        return Nette\Utils\Arrays::get($data, $name, $default);
    }

    public function setValue($name, $value)
    {
        $data = $this->getRawData();
        $data[$name] = $value;
        $this->setRawData($data);
        return $this;
    }

    public function unsetValue($name)
    {
        $data = $this->getRawData();
        if(isset($data[$name]))
            unset($data[$name]);
        $this->setRawData($data);
        return $this;
    }

    public function issetValue($name)
    {
        $data = $this->getRawData();
            return isset($data[$name]);
    }

}