Nette 2.3.0 beta for testing

Notice: This thread is very old.
David Grudl
Nette Core | 8111
+
+31
-

I'd like to announce the beta of Nette 2.3.0.

The beta is intended for bug fixing prior to the stable release. Please test this release against your code and report any problems that you encounter. Next release should show up in two weeks.

You can download ZIP archive or use Composer:

	"require": {
		"nette/nette": "~2.3.0"
	},
	"minimum-stability": "beta",
	"prefer-stable": true

Application

  • all presenters are created in Dependency Injection container
  • added LinkGenerator
  • Routing: speed optimization & caching, action name can begin with number

BC breaks to be discussed:

  • removed case insensivity for presenter and action names
  • removed support for deprecated Nette\Templating, template extension .phtml and old link syntax

not merged yet:

  • MessagesStorage & RequestStorage #4
  • macro {link} working without presenter

Bootstrap

  • added Configurator::addServices()
  • removed constants Configurator::DEVELOPMENT & PRODUCTION (BC break)

Caching

  • FileStorage: removed usage of realpath()

Database

  • throws own exceptions:
    • DriverException, ConnectionException
    • ConstraintViolationException, ForeignKeyConstraintViolationException, NotNullConstraintViolationException and UniqueConstraintViolationException
  • added support for += and -= in UPDATE statement
  • added support for operators in WHERE & AND
  • implemented ?and ?or ?set ?values ?order ?name
  • added support for ‘.’ in column names
  • classes *Reflection split into with *Conventions & Structure
  • added IRowContainer::fetchAssoc(), ISupplementalDriver::convertException() (BC break)
  • MySqlDriver: uses utf8mb4 encoding for MySQL >= 5.5.3
  • Connection: undeprecated some methods

Deprecated

new package for deprecated stuff

DI

  • parameters auto-resolution for generated factories
  • added support for service aliases
  • added DecoratorExtension, DIExtension and InjectExtension
  • added CompilerExtension::validateConfig()
  • ExtensionsExtension: allows to pass params
  • dynamic services
  • chained syntax Class::method()::method()::method()

not merged yet:

  • better CompilerBuilder API

Finder

  • Finder::filter() callback always receives as argument (at least) a FilesystemIterator

Forms

  • to Container::onValidate callbacks are passed values via second parameter
  • added bridge for Nette DI
  • Rules::$defaultMessages and all validating methods in BaseControl and it's descendants moved to Nette\Forms\Validator

BC breaks to be discussed:

  • addText, addPassword, addTextArea: parameter $cols is deprecated
  • buttons and hidden fields are generated without HTML attribute ID by default

not merged yet:

  • setTranslator(NULL) will not stop translate label (#58)
  • IValidator as base class for own validators

Http

  • RequestFactory: speed optimizations
  • Url: internally stores query parameters as array, improved canonicalize(), etc…
  • added Helpers::formatDate()
  • added IResponse::getHeader() (BC break)
  • Request::getUrl() is immutable
  • Response::date(), Request::isPost() & Request::getFile() with multiple keys are deprecated

Latte

  • template is wrapped in an class › much faster repeated rendering
  • faster loading from cache file
  • {ifset block} & {elseifset block} without #
  • added macro {php …} as replacement for {? …}
  • faster autoloader for non-Composer usage
  • fills Html::$attrs with actual attribute values
  • “words” can contain concatenation dots (i.e. {include $dir . '/template.latte'} nette/latte#26)
  • parser detects for unclosed / malformed macros (nette/nette#711)
  • added support for <script type="text/html"> (nette/latte#24 & nette/nette#705)
  • combination of n:class & class leads to exception

Mail

  • deprecated support for Nette\Templating

Neon

  • chained syntax first(a, b)second(1, 2)

Php Generator

  • generating PHP files with multiple namespaces & classes
  • short phpDoc for properties

Reflection

  • added Helpers::getDeclaringClass()

Robot Loader

  • added support for loading from Phar
  • removed usage of realpath()

Safe Stream

  • added protocol nette.safe://, alias for safe://

Security

  • User: bool parameters replaced with flags, i.e. $user->setExpiration('20 minutes', TRUE, TRUE) › setExpiration('20 minutes', $user::BROWSER_CLOSED | $user::CLEAR_IDENTITY)

Tracy

  • Bluescreen & Debug Bar: 10× smaller HTML code, 10× faster, deeper depth of dumps
  • Bluescreen: dumps contain location of class definition (can be opened in editor with ctrl key)
  • Bluescreen: added link “skip error” to suppress strictMode
  • Bluescreen: added Exception panel
  • added Tracy\ILogger and rewritten default Logger
  • Debugger::enable() implements checking of cookie (format cookie@ip.address)
  • customizable 500 error template via Debugger::$errorTemplate
  • Dumper: new options LOCATION_SOURCE, LOCATION_LINK, LOCATION_CLASS
  • Dumper: customizable object exportes
  • completely rewritten JavaScript, now requires IE 10+ (removed tracyQ.js)

Utils

  • added Arrays::normalize(), Callback::invokeSafe(), Html::data(),
  • Image::from() throws ImageException when is unable to decode file
  • Callback::closure() returns native closures since PHP 5.4
  • Strings::chr() throws Nette\InvalidArgumentException if code point is not in valid range
  • Validators::isUrl() accepts underscores in subdomains
hrach
Member | 1834
+
+2
-

removed case insensivity for presenter and action names

Well, I would postpone this to 3.0, since there is not any tool, which would safely check all my links, that they are valid. However, such tool could make the migration easier and BC break defensible for 2.3.

Jan Tvrdík
Nette guru | 2595
+
0
-

@hrach Most cases could be checked with a simple regexp:

(link|redirect|n:href=)[\s("':]+[a-z]\w*:

Last edited by Jan Tvrdík (2015-02-02 17:42)

David Grudl
Nette Core | 8111
+
+1
-

@hrach I added this, it throws warning when link or router has wrong case and should maintain BC.

hrach
Member | 1834
+
0
-

@DavidGrudl fair solution! Thanks!
@JanTvrdík yes and then I will have to check them all manually. However, probably I will have to, so thanks, it will be handy.

potapnik
Member | 127
+
0
-

The generated temp/cache/Nette.Configurator/Container_xxx.php ends with public function create():

<?php
	Nette\Utils\Html::$xhtml = FALSE;;
	return $service;
?>

Why doubling ;; on the xhtml setup line?

Mikulas Dite
Member | 756
+
0
-

What was the reason for nette/application: Route: <action> can be a number (BC break)?

https://github.com/…72e84c9bc90e

It broke almost all my routes :/ Not the worst thing ever as it can be fixed with \D+ postfix in route definition but it seems like an arbitrary bc anyway.


Other than that the RC is solid, the only other thing that seems to broke was minor ILogger collision with Kdyby\Monolog. Thumbs up!

Last edited by Mikulas Dite (2015-02-05 13:59)

blindAlley
Member | 31
+
0
-

I'm little bit afraid of change with moving presenters into container.

We have overloaded presenters loading mechanism. It depends on particular presenter file path and file_exists() calls, so it cannot be used with the presenters in container I think. Robot loader currently also skip folders with presenters.

Is this scenario usable in 2.3 same way it was in 2.2 – just use own PresenterFactory?

David Grudl
Nette Core | 8111
+
+3
-

@MikulasDite I didn't realized how big BC break this is. I'll revert it.

David Grudl
Nette Core | 8111
+
0
-

@blindAlley it should work with your own loader, but please test it. If it will not work, open new thread here on forum.

Filip Procházka
Moderator | 4668
+
+2
-

@MikulasDite I've fixed the BC in Kdyby/Monolog, it should work now. Please report it to github next time, thank you :)

David Grudl
Nette Core | 8111
+
+5
-

One week later and beta2 is here.

  • Application: reverted that action name can begin with number
  • PresenterFactory: fixed compatibility with case mismatched presenter names
  • Bootstrap::setDebugMode – argument must be string|array|bool
  • DI: removed dependency on nette/reflection
  • DI: magic methods replaced with native ones (is 3× faster)
  • DI: implemented escaping of ‘@’ at the beginning of string
  • DI\Container::findByType() returns all services, including non-autowired (BC break!!)
  • Forms: reverted that addText, addPassword, addTextArea: parameter $cols is deprecated
  • Forms: added deprecation warning to deprecated addFilter()
  • Forms: added RadioList::$generateId that enables generating of ID
  • PhpGenerator: magic methods replaced with native ones
  • RobotLoaders: warns on case mismatch on class name
  • … and some bugs fixed

All components are finished. Only nette/application is in beta phase, because nette/application#4 is not merged yet.

enumag
Member | 2118
+
+1
-

@DavidGrudl I'm confused about nette/application#4. There are several PRs in several repos, some closed, other open. Which implementation is up-to-date? Where should I track the progress?

https://github.com/…ation/pull/4
https://github.com/…tion/pull/17
https://github.com/…tion/pull/18
https://github.com/…/http/pull/5
https://github.com/…/http/pull/6

David Grudl
Nette Core | 8111
+
0
-

I'll probably will close all of them and create new PR.

Mikulas Dite
Member | 756
+
0
-

Just a heads up, commit nette/di@2.3.0-RC2: class names are case sensitive (BC break)

https://github.com/…3e4af052c0e1

breaks on @PetrP​'s ORM, because it lowercases all class names. I believe the commit should stay in 2.3 however.

Hotfix https://gist.github.com/…e48bd2bb142d (relevant issue
https://github.com/…rm/issues/63)


Again, otherwise 2.3.0-RC2 works great!

Last edited by Mikulas Dite (2015-02-06 19:38)

o5
Member | 416
+
+1
-

If you use Nette\Database like me, check this. After update to Nette 2.3 beta I got this message:

SQLSTATE[42000]: Syntax error or access violation: 1253 COLLATION 'utf8_general_ci' is not valid for CHARACTER SET 'utf8mb4'

I looked into changelog and I saw this point:

  • MySqlDriver: uses utf8mb4 encoding for MySQL >= 5.5.3

So after a hour of searching, I added options: [charset: utf8] and problem was resolved.

database:
	dsn: 'mysql:host=localhost;dbname=database'
	user: username
	password: password
	options: [charset: utf8]

Is it about this patch and I absolutely don't understand the benefits of the new behaviour.

Last edited by o5 (2015-02-19 09:15)

David Grudl
Nette Core | 8111
+
0
-

According to http://dev.mysql.com/…grading.html

SET NAMES ‘utf8mb4’ causes use of the 4-byte character set for connection character sets. As long as no 4-byte characters are sent from the server, there should be no problems.

Are you doing with database something special?

o5
Member | 416
+
0
-

David Grudl wrote:

Are you doing with database something special?

I think not.

SELECT *
FROM `table`
WHERE (`column` LIKE 'ro%' COLLATE `utf8_general_ci`)
LIMIT 10
Jan Tvrdík
Nette guru | 2595
+
0
-

@o5 Hm… that query breaks even the latest Adminer for the same reason.

o5
Member | 416
+
0
-

@JanTvrdík Yes, I read twitter :)

David Grudl
Nette Core | 8111
+
0
-

So now I do not know if I should uft8mb4 support revert… Probably yes.

romiix.org
Member | 343
+
0
-

Why is deprecated support for Nette\Templating in Mail?

enumag
Member | 2118
+
0
-

@romiix.org Because Nette\Templating is deprecated as whole and because the support is not needed. You can just call $message->setHtmlBody($template->__toString());.

romiix.org
Member | 343
+
0
-

@enumag Thanks;)

David Grudl
Nette Core | 8111
+
+8
-

Nette 2.3 beta 3 has been released:

  • Application: reverted disabled canonicalization for restored requests
  • Http: reverted that script path detection is case-sensitive
  • DatabaseExtension: fixed autowiring of multi connections
  • Database: SqlProcessor converts objects with __toString to strings
  • DI: removed support for dynamically added extensions (BC break!) [Closes #50]
  • DI: removed support for section services inside extensions (BC break)
  • DI: InjectExtension is called as the last one [Closes #53]
  • Parser: fixed syntax=off

bonus:

  • vector icons on Tracy Bar
chemix
Nette Core | 1296
+
0
-

If I installed new version I get these errors:

problem in latte with class

Latte\CompileException
It is not possible to combine class with n:class in`

from

<div class="row" n:class="$input->required ? required">

to

<div n:class="$input->required ? required, row">

fixed


sending email from template

User Deprecated
Support for Nette\Templating is deprecated

from

	$mail->addTo($email)
	->setHtmlBody($template);

to

	$mail->addTo($email)
	->setHtmlBody((string)$template);

fixed


when the email template use <img src=

Nette\FileNotFoundException
Unable to read file ‘/image/logo.png’.

from

<img src="image/logo.png"  />
	$mail->->setHtmlBody($template);

to

$mail->setHtmlBody((string)$template, dirname($template->getFile()));

fixed (thanx @enumag)

Last edited by chemix (2015-02-16 22:18)

enumag
Member | 2118
+
+3
-

@chemix Look at the method setHtmlBody. It parses the HTML code to add all the images as attachments. The path to the images was detected automatically before from the Template object which is deprecated now. You should fix that by adding the second argument like this:

$mail->setHtmlBody((string) $template, dirname($template->getFile());
David Grudl
Nette Core | 8111
+
0
-

@chemix I changed it a little bit, is it better? https://github.com/…fe9342eb35f9. The (string) $template is not required now. But setting i.e. $mail->subject inside template will not work unless you manually add $mail parameter to template.

chemix
Nette Core | 1296
+
0
-

@DavidGrudl looks fine, but one question. Why you use “E_USER_WARNING” and not “E_USER_DEPRECATED” https://github.com/…fe9342eb35f9#…

Milo
Nette Core | 1283
+
+1
-

One older app updated without bigger problems. One silent issue is case-sensitivity of a route mask.

# didn't match lowercased URL
'<lang cs|en>/<presenter Private|Settings|Search|Admin>/<action>[/<id>]'

# fixed mask is matching now
'<lang cs|en>/<presenter private|settings|search|admin>/<action>[/<id>]'

It is not issue for me, just note.

David Grudl
Nette Core | 8111
+
0
-

@Milo I'd add some warnings, but I do not know how to do it.

And this is confusing… <presenter=Private private|settings|search>/<action=default>

David Grudl
Nette Core | 8111
+
+8
-

I'd like to announce the release candidate Nette 2.3.0 RC. I believe this is the last release before stable. It already runs on (nearly) all my sites, so please, try it too.

In this release, there are fixes based on your feedback, like improved messages, un-deprecated stuff etc:

  • Forms: un-deprecated addFilter(), now is integrated to rules
  • Mail: removed deprecation notices for Nette\Templating and Nette\Application\UI\ITemplate, but now if you use in templates variable $mail, you have to pass it manually

There are also new deprecation notices for very old and ugly things:

  • deprecated Route::addStyle() & Route::setStyleProperty() now trigger E_USER_DEPRECATED
  • Cache: deprecated ArrayAccess (i.e. $cache[$key] = $val instead of $cache->save($key, $val) etc) triggers E_USER_DEPRECATED
  • and some stuff that triggers errors in Nette 2.1 / 2.2 was removed

It contains slightly redesigned ContainerLoader & Compiler (will be described later). And improved netteForms.js, where some limitations was removed. Please place effort to test netteForms.js.

David Grudl
Nette Core | 8111
+
+13
-

Migration guide

Application
  • routes and presenter names are case sensitive. Nette will warn you if you use the wrong case in presenter name. But due to performance limitation it is not checking Route mask – you should check them manually. Correct is <presenter=UpperCasedDefaultValue> and <presenter url-cased-regexp-mask>.
  • Route::addStyle() & Route::setStyleProperty() are deprecated and now will trigger E_USER_DEPRECATED
  • unsupported template extension .phtml and old link syntax
Bootstrap
  • removed deprecated constants Configurator::DEVELOPMENT and PRODUCTION
  • Configurator::setDebugMode() accepts only bool / string / array
  • in config file you can move all sections placed in nette to one level up. If you move up one of the sections container, mailer or debugger, rename it to di, mail and tracy.
Caching
  • ancient and deprecated ArrayAccess syntax $val = $cache[$key] or $cache[$key] = $val triggers E_USER_DEPRECATED. Use please $cache->load($key) and $cache->save($key, $val)
Database
  • MySqlDriver by default uses utf8mb4 encoding for MySQL >= 5.5.3 instead of utf8 (see, maybe it will be reverted)
  • IReflection was changed to twins IStructure and IConventions
  • to ensure that new SQL translator do the same job as older one, you can install special tool named CompatibilityChecker22
DI
  • removed support for placing services inside extension section in configuration file
  • removed support for dynamically added extensions
Finder
  • Finder::filter() callback always receives as argument (at least) a FilesystemIterator
Forms
  • internal filtering methods like Nette\Forms\Controls\TextBase::filterFloat was removed
  • internal validation methods like Nette\Forms\Controls\TextBase::validateFloat was moved to Nette\Forms\Validator, as well as Rules::$defaultMessages
  • Buttons and Hidden fields are generated without HTML ID. Relying on autogenerated ID is very bad, if you want ID, set it via setHtmlId()
  • RadioList items are generated without ID too. You can enable it via $radioList->generateId = TRUE. But again: set you base ID via setHtmlId()
  • filters added via TextBase::addFilter() are processed during validation.
  • now you can add filters to conditions $input->addCondition(...)->addFilter(...)
Http
  • Request::getUrl() is immutable
Mail
  • if you use variable $mail in template, you have to pass it to the template manually
  • but better than {var $mail->subject = "Your new order"} is this <title>Your new order</title>, isn't it?
  • if you have linked images (with relative paths) in template, pass base file path to images as second parameter to setHtmlBody()
  • there is no need to cast templates to (string)
RobotLoader
  • is now case sensitive and will warn you if you use the wrong case in class name
SafeStream
  • it is recommended to change protocol safe://... to namespaced nette.safe://...
Tracy
  • fasten your belt if you will use Tracy, she is now really fast :-)
Utils
  • Image::from() throws ImageException when is unable to decode file
  • Image::getFormatFromString is deprecated
  • Strings::chr and normalize now works only with UTF-8 encoding
  • Strings::chr() throws Nette\InvalidArgumentException if code point is not in valid range
mrtnzlml
Member | 140
+
0
-

Hi. I have very strange problem with two projects on Nette 2.3. If I deleted the cache then I launched tests using Nette\Tester and then I opened the project in the browser (or vice versa – delete cache, open in the browser and run the tests), I got something like Fatal Error: Class ‘Template6204ecb8aa28def219f530ae783277ec’ not found. To be honest, I have no idea what's going on and I am not sure if it's bug or it's problem in my code (because nobody noticed). This behavior is only with new verion of Nette. I know, it's not very verbose error – do you need a bluescreen? Any idea?

Eda
Backer | 220
+
0
-

I tryed new Nette 2.3 a I didnt noticed any bigger problems, but only speed enhancement :-)


Only one note to new SqlParser in Nette\Database:

$this->db->query('SELECT ... WHERE id IN (?)', []);

In Nette 2.2 generated:

SELECT ... WHERE id IN (1=1)

And script didnt crashed. In Nette 2.3 it generates (right) SQL:

SELECT ... WHERE id IN ()

And script crashes.

Last edited by Eda (2015-02-19 23:13)

David Grudl
Nette Core | 8111
+
0
-

@mrtnzlml in which file and on which line?

@Eda fixed

mrtnzlml
Member | 140
+
0
-

David Grudl wrote:

@mrtnzlml in which file and on which line?

Latte\Engine.php:95

David Grudl
Nette Core | 8111
+
0
-

And template file exists? Contains a class?

Milo
Nette Core | 1283
+
0
-

Just updated one simple 2.0.8 directly to 2.3.0-RC and no problem. Few lower-case links warnings, cache array access warnings and helper loader exception and that's all. I really appreciate the “deprecation messages guide”. For such applications, BC is great!

mrtnzlml
Member | 140
+
0
-

David Grudl wrote:

And template file exists? Contains a class?

No, it doesn't exist. This name occurs only in the robotloader cache file. Another weird thing. There are *.php and *.php.lock files with the same name (not related to the tests). I didn't notice this behavior in previous versions. It doesn't look good.

Maybe the problem is related to the fact, that I am trying to run templates in tests (like this) I guess. It's because It doesn't work when the cache is generated using tests. It works only if the cache is generated in the same environment a want to access later without troubles. Is that possible?

I just noticed that there are mentioned two classes form the diferend project (if I run the tests first) at the end of the robotloader file. I should look how does it work actually. How it's even possible, that it knows about this classes? And again – it occurs only in robotloader. Same as the Template* name…

David Grudl
Nette Core | 8111
+
0
-

@mrtnzlml RobotLoader is indexing your temp dir? Yes, it can break Latte.

mrtnzlml
Member | 140
+
0
-

David Grudl wrote:

@mrtnzlml RobotLoader is indexing your temp dir? Yes, it can break Latte.

No. Only app folder. Nothing unusual.

David Grudl
Nette Core | 8111
+
0
-

@mrtnzlml Do you run tests in multiple threads with the same temp dir? Is temp dir cleaned by purge()?

mrtnzlml
Member | 140
+
0
-

David Grudl wrote:

@mrtnzlml Do you run tests in multiple threads with the same temp dir? Is temp dir cleaned by purge()?

I am trying to figure this out in one project I started about month ago so the test bootstrap is very similar to the sandbox one. It means the same temp dir for every test (i default 8 thread mode) without purge. Obviously it works if I am using different temp dir for tests and different for the classic way. Is this the right solution? Should I use more temp directories? And if so, should it be also in the sandbox?

David Grudl
Nette Core | 8111
+
0
-

@mrtnzlml Multithread without purge seems fine. Can you try to apply this commit? Or send me email with minimal failing code?

mrtnzlml
Member | 140
+
0
-

David Grudl wrote:

@mrtnzlml Multithread without purge seems fine. Can you try to apply this commit? Or send me email with minimal failing code?

This revert doesn't solve the issue. It is the reason of the *.php.lock files in latte cache, but it's not the reason of my fatal error.

I figured out what's the reason of this fatal error and it's definitely in my code, but I think that this behavior is quite brutal and as you will see it doesn't look like fatal error in my code. I just downloaded nette\sandbox with stability dev and created this simple method in default test case:

function testRenderDefault()
{
	$presenterFactory = $this->container->getByType('Nette\Application\IPresenterFactory');
	$presenter = $presenterFactory->createPresenter('Homepage');
	$presenter->autoCanonicalize = FALSE;

	$request = new Nette\Application\Request('Homepage', 'GET', array('action' => 'default'));
	$response = $presenter->run($request);

	Tester\Assert::true($response instanceof Nette\Application\Responses\TextResponse);
	Tester\Assert::true($response->getSource() instanceof Nette\Application\UI\ITemplate);

	$html = (string) $response->getSource(); //ERR
	// $html = $response->getSource(); //OK

	return $response;
}

Result: Fatal Error: Class ‘Templated9516166f211b79e2d4660dd2994d776’ not found

So the reason is string typecast. I read something with string casting before but it's only related to the email templates, right? I can send you the sandbox if you want to. I don't know why is that and how to fix it (or if it should be fixed).

Win 8.1, PHP 5.5.15

potapnik
Member | 127
+
0
-

Hi, based on @FilipKlimeš advise in other thread – I have the same problem, installed standard sandbox from composer by composer create-project nette/sandbox:dev-master on Win8.1, PHP 5.6.3. I am using preconfigured test bootstrap.php from sandbox, my HomepageTester.phpt is:

<?php

namespace Test;

use Nette;
use Tester;
use Tester\Assert;
use Tester\DomQuery;

$container = require __DIR__ . '/bootstrap.php';

class HomepageTest extends Tester\TestCase
{
	private $container;
	private $presenterFactory;

	public function __construct($container) {
		$this->container = $container;
		$this->presenterFactory = $container->getByType('Nette\Application\IPresenterFactory');
	}

	public function testPresenter() {

		$presenter = $this->presenterFactory->createPresenter('Homepage');
		$presenter->autoCanonicalize = FALSE;
		$request = new Nette\Application\Request('Homepage', 'GET');
		$response = $presenter->run($request);
		Assert::true($response instanceof Nette\Application\Responses\TextResponse);
		$html = (string) $response->getSource();
		$dom = DomQuery::fromHtml($html);
		Assert::true($dom->has('h1'));
		//Assert::true(()$response->getSource() instanceof Nette\Templating\ITemplate);
	}
}

$test = new HomepageTest($container);
$test->run();

?>

And I am running tests from root dir of project like this: vendor\bin\tester.bat tests with the same error on same line. Temp/cache/latte has four files – app-presenters-templates-Homepage-default-latte-8354b9ee37402c56966d6117507959df.php and dtto.lock and sandbox23-app-presenters-templates-layout-latte-6abc03c4c22263ffe7129c881e124246.php and dtto.lock. Maybe the problem is that sandbox23 is part of the file name…sandbox23 is the name of project dir.

potapnik
Member | 127
+
0
-

If I remove the string typecast, it works OK.

Milo
Nette Core | 1283
+
+3
-

@DavidGrudl @potapnik @mrtnzlml Reproduced

David Grudl
Nette Core | 8111
+
+3
-

Fixed. World is saved!