siblings() error: InvalidArgumentException: The current node list is empty - php

I have an error in symfony2 unit testing , symfony : 2.7.1
when I use siblings() I have a the error:
InvalidArgumentException: The current node list is empty.
the twig file:
<h1>ddd</h1>
<p>ahmedghgh</p>
<ul>
<li>dddd</li>
<li>eeee</li>
<li>ffff</li>
</ul>
</p>bye</p>
<form action ="" method="GET" name ="nameForm">
<input type="text" value ="name" name="name">
<input type="submit" value ="send" name="send">
</form>
BasicControllerTest.php
<?php
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
namespace TestingSymfony\BasicBundle\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class BasicControllerTest extends WebTestCase {
public function testHelloContent() {
$client = static::createClient();
$crawler = $client->request('GET', '/helloworld');
$h1 = $crawler->filter('h1')->eq(0);
$p1 = $crawler->filter('p')->first();
$ul = $p1->siblings()->eq(0);
$l1 = $ul->children()->first();
$l2 = $ul->children()->eq(1);
$l3 = $ul->children()->last();
$p2 = $crawler->filterXPath("//p")->last();
}
}
Once I remove the siblings , all is ok and no error appeared

You have a typo in the twig files: check that the P tag is open and closed correclty, as follow:
<p>bye</p>
instead of
</p>bye</p>
Hope this help

Your filterdid not return any results as you had a typo. That is why it crashed. However, for others who did not have any typo, that's how I solved this issue, by adding a try catch.
try {
$p1 = $crawler->filter('p')->first();
} catch (\InvalidArgumentException $e) {
// Handle the current node list is empty..
}

Related

TYPO3 7.6.10: How to extend the felogin extension?

I tried to extend the core extension felogin with an extra extension called "feloginextended".
I want to add the first_name and the last_name property of the current user into my logout formular.
This is my overridden template (only the logout part):
<!--###TEMPLATE_LOGOUT###-->
<form class="login-form" action="###ACTION_URI###" target="_top" method="post">
<div>
<div class="user">###FIRSTNAME### ###LASTNAME###</div>
<a class="page-link-button" href="http://tf.lightblue.eu/index.php?id=14">Meine Siegel</a>
<a class="page-link-button" href="http://tf.lightblue.eu/index.php?id=15">Mein Account</a>
<input class="form-btn" type="submit" name="submit" value="Logout" />
</div>
<div class="felogin-hidden">
<input type="hidden" name="logintype" value="logout" />
<input type="hidden" name="pid" value="###STORAGE_PID###" />
<input type="hidden" name="###PREFIXID###[noredirect]" value="###NOREDIRECT###" />
</div>
</form>
<!--###TEMPLATE_LOGOUT###-->
Then I added the Controller Classes\Xclass\FrontendLoginController to my extension.
I copied the original file and add some changes in the showLogout function, to set the markers:
<?php
namespace Typo3\feloginextended\Xclass;
use \TYPO3\CMS\Frontend\Plugin\AbstractPlugin;
/**
* Plugin 'Website User Login' for the 'felogin' extension.
*/
class FrontendLoginController extends AbstractPlugin
{
/**
* Shows logout form
*
* #return string The content.
*/
protected function showLogout()
{
$subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_LOGOUT###');
$subpartArray = ($linkpartArray = array());
$markerArray['###STATUS_HEADER###'] = $this->getDisplayText('status_header', $this->conf['logoutHeader_stdWrap.']);
$markerArray['###STATUS_MESSAGE###'] = $this->getDisplayText('status_message', $this->conf['logoutMessage_stdWrap.']);
$this->cObj->stdWrap($this->flexFormValue('message', 's_status'), $this->conf['logoutMessage_stdWrap.']);
$markerArray['###LEGEND###'] = $this->pi_getLL('logout', '', true);
$markerArray['###ACTION_URI###'] = $this->getPageLink('', array(), true);
$markerArray['###LOGOUT_LABEL###'] = $this->pi_getLL('logout', '', true);
$markerArray['###NAME###'] = htmlspecialchars($this->frontendController->fe_user->user['name']);
$markerArray['###STORAGE_PID###'] = $this->spid;
$markerArray['###USERNAME###'] = htmlspecialchars($this->frontendController->fe_user->user['username']);
$markerArray['###USERNAME_LABEL###'] = $this->pi_getLL('username', '', true);
$markerArray['###NOREDIRECT###'] = $this->noRedirect ? '1' : '0';
$markerArray['###PREFIXID###'] = $this->prefixId;
// my custom changes-----------------------------------
$markerArray['###FIRSTNAME###'] = htmlspecialchars($this->frontendController->fe_user->user['first_name']);
$markerArray['###LASTNAME###'] = htmlspecialchars($this->frontendController->fe_user->user['last_name']);
//------------------------------------------------------
$markerArray = array_merge($markerArray, $this->getUserFieldMarkers());
if ($this->redirectUrl) {
// Use redirectUrl for action tag because of possible access restricted pages
$markerArray['###ACTION_URI###'] = htmlspecialchars($this->redirectUrl);
$this->redirectUrl = '';
}
return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
}
}
Then I register my template in the ext_typoscript_setup.txt file:
plugin.tx_felogin_pi1 {
templateFile = EXT:feloginextended/Resources/Private/Templates/FrontendLogin.html
}
And my final step was the registration of the controller in the ext_localconf.php:
<?php
if (!defined('TYPO3_MODE')) {
die('Access denied.');
}
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\\CMS\\Felogin\\Controller\\FrontendLoginController'] = array(
'className' => 'Typo3\\Feloginextended\\Xclass\\FrontendLoginController',
);
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['tx_felogin_pi1'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\\CMS\\Felogin\\Controller\\FrontendLoginController'];
If add this changes into the original files of the felogin extension, then I have a solution.
But this way is very dirty and in the future I can't update the felogin extension easily.
I found this "solution": https://forum.typo3.org/index.php/t/202500/
But it don't work for me.
Have anyone an idea or have an other way to bring the first and the last name of the current user to the logout formular?
EDIT:
I get everytime a http error 500!
Thanks Felix
The solution is pretty simple. You can just add the markers ###FEUSER_FIRST_NAME### and ###FEUSER_LAST_NAME### to your template and they will be replaced by the right values. This schema is general and can be used on all fields of the user:
###FEUSER_{DB field in uppercase}###. Note that the fields are used with underscores and not the lower camelcase.
This works in TYPO3 6.x and the code looks the same in 7.6 so it should work too.
Assumed that your extension EXT:feloginextended is installed and you cleared all caches including the full cache clear provided by the install tool, you have done everything correct. Delete also the directory /typo3temp/autoload completely.
The only thing which may be wrong is the loading order of the extensions, which is important in case you define your TS-Setup inside the file ext_typoscript_setup.txt.
In this case you must force your extension to be loaded after the original EXT:felogin extension. And the only way to assure that is to add the extension felogin to the list of "suggests" constraint setting inside EXT:feloginextended/ext_emconf.php.
Then you must fully deinstall your extension and install it again.
$EM_CONF[$_EXTKEY] = array(
[...]
'constraints' => array(
[...]
'suggests' => array(
'felogin' => '7.6.0-7.6.99'
),
)
);
To continue the answer after your error 500 information.
This must be a class loader problem as well, the fact that you are seeing 500 error is caused by PHP or TYPO3 error reporting configuration.
Anyway I copied your approach as follows:
EXT:my_extension/ext_localconf.php
<?php
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\CMS\Felogin\Controller\FrontendLoginController'] = array(
'className' => 'Typo3\Feloginextended\Xclass\FrontendLoginController',
);
$GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['tx_felogin_pi1'] = $GLOBALS['TYPO3_CONF_VARS']['SYS']['Objects']['TYPO3\\CMS\\Felogin\\Controller\\FrontendLoginController'];
EXT:my_extension/ext_typoscript_setup.txt
plugin.tx_felogin_pi1 {
templateFile = EXT:my_extension/FrontendLogin.html
}
EXT:my_extension/Classes/FrontendLoginController.php
<?php
namespace Typo3\Feloginextended\Xclass;
use TYPO3\CMS\Felogin\Controller\FrontendLoginController as BaseFrontendLoginController;
/**
* Plugin 'Website User Login' for the 'felogin' extension.
*/
class FrontendLoginController extends BaseFrontendLoginController
{
/**
* Shows login form
*
* #return string The content.
*/
protected function showLogin()
{
$subpart = $this->cObj->getSubpart($this->template, '###TEMPLATE_LOGIN###');
$subpartArray = ($linkpartArray = array());
$markerArray['###MY_MARKER###'] = 'My new login';
return $this->cObj->substituteMarkerArrayCached($subpart, $markerArray, $subpartArray, $linkpartArray);
}
}
EXT:my_extension/FrontendLogin.html
[...]
<!--###TEMPLATE_LOGIN###-->
###MY_MARKER###
<!--###TEMPLATE_LOGIN###-->
<!--###TEMPLATE_LOGOUT###-->
My New Logout
<!--###TEMPLATE_LOGOUT###-->
[...]
The result is totally correct instead of the login form I see 'My New Login', so everything is working for me.
The solution for you is:
1) You have a typo in the namespace. It must be namespace Typo3\**F**eloginextended\Xclass; instead of namespace Typo3\**f**eloginextended\Xclass;
2) You must inherit from TYPO3\CMS\Felogin\Controller\FrontendLoginController
Do not forget to clear typo3temp/Cache/* and typo3temp/autoload/* !

Owncloud 8.1 "myapp" sample, add a function to write to a file

On Owncloud 8.1 using the owncloud command line, I create a new test app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 8
The app is working, I can add it in the owncloud control panel.
Now I'd like to write to a file, so I use one example from the owncloud documentation:
https://doc.owncloud.org/server/8.1/developer_manual/app/filesystem.html
[Edit] I started over and now, I don't know if I omitted something, but "myapp" comes with no "application.php" file.
So I create it at /var/www/core/apps/myapp/appinfo/application.php :
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Storage\AuthorStorage;
class Application extends App {
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Storage Layer
*/
$container->registerService('AuthorStorage', function($c) {
return new AuthorStorage($c->query('RootStorage'));
});
$container->registerService('RootStorage', function($c) {
return $c->query('ServerContainer')->getRootFolder();
});
}
}
Then I create a file called /var/www/core/apps/myapp/storage/AuthorStorage.php with:
<?php
namespace OCA\MyApp\Storage;
class AuthorStorage {
private $storage;
public function __construct($storage){
$this->storage = $storage;
}
public function writeTxt($content) {
// check if file exists and write to it if possible
try {
try {
$file = $this->storage->get('/myfile.txt');
} catch(\OCP\Files\NotFoundException $e) {
$this->storage->touch('/myfile.txt');
$file = $this->storage->get('/myfile.txt');
}
// the id can be accessed by $file->getId();
$file->putContent($content);
} catch(\OCP\Files\NotPermittedException $e) {
// you have to create this exception by yourself ;)
throw new StorageException('Cant write to file');
}
}
}
The sample app already gives me a route to the index function in the pagecontroller.php
['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
How do I call the function "writeTxt" from there?
Based on http://php.net/manual/en/language.oop5.basic.php
I tried:
use \OCA\MyApp\Storage\AuthorStorage;
and
public function index() {
//added part
$a = new AuthorStorage();
$a->writeTxt('test');
//original part
$params = ['user' => $this->userId];
return new TemplateResponse('myapp', 'main', $params); //templates/main.php
}
After running I get a "Class 'OCA\MyApp\Storage\AuthorStorage' not found at /var/www/core/apps/myapp/controller/pagecontroller.php#44"
Even with the help of use \OCA\MyApp\Storage\AuthorStorage; ( ClassNotFoundException: Attempted to load class... Symfony ) it doesn't seem to help.
Thanks
Time has gone by, so I'm posting an answer to my question for owncloud 9.
Here are the steps to a basic script with read, write, copy file ability.
"application.php" has definitively been removed from the example. It was not a bug.
Following:
https://doc.owncloud.org/server/9.0/developer_manual/app/startapp.html
Generate the demo "MyApp" app:
ocdev startapp MyApp --email mail#example.com --author "Your Name" --description "My first app" --owncloud 9
Edit the file myapp/controller/pagecontroller.php
<?php
/**
* ownCloud - myapp
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* #author Your Name <mail#example.com>
* #copyright Your Name 2016
*/
namespace OCA\MyApp\Controller;
use OCP\IRequest;
use OCP\AppFramework\Http\TemplateResponse;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\Controller;
use OCP\Files\IRootFolder;
use OC\Files\Storage\Temporary;
class PageController extends Controller {
private $userId;
private $storage;
private $userstorage;
public function __construct($AppName, IRequest $request, IRootFolder $storage, $UserId){
parent::__construct($AppName, $request);
$this->storage = $storage;
$this->userId = $UserId;
$this->userstorage = $this->storage->get($this->userId.'/files/');
}
/**
* CAUTION: the #Stuff turns off security checks; for this page no admin is
* required and no CSRF check. If you don't know what CSRF is, read
* it up in the docs or you might create a security hole. This is
* basically the only required method to add this exemption, don't
* add it to any other method if you don't exactly know what it does
*
* #NoAdminRequired
* #NoCSRFRequired
*/
public function index() {
$listedudossier = $this->userstorage->getDirectoryListing();
//list all items in the root directory
//and copies the files in an directory called old
//the directory "old" is not script created
foreach ($listedudossier as $value) {
if ( $value->getType() == 'file' ){
$value->copy($this->userId.'/files/old/'.$value->getName());
//also works
//$value->copy($this->userstorage->getPath().'/old/'.$value->getName());
}
}
$params = ['listedudossier' => $listedudossier ];
return new TemplateResponse('myapp', 'main', $params); // templates/main.php
}
/**
* Simply method that posts back the payload of the request
* #NoAdminRequired
*/
public function doEcho($echo) {
//creates a file
$this->userstorage->newFile('myfile2.txt');
//opens a file, adds inputbox content and saves the file
$file = $this->userstorage->get('myfile.txt');
$contenu = $file->getContent();
$file->putContent($contenu.$echo);
return new DataResponse(['echo' => $echo]);
}
}
You also need to edit the myapp/templates/part.content.php
<p>Hello World <?php p($_['user']) ?></p>
<p><button id="hello">click me</button></p>
<p><textarea id="echo-content">
Send this as ajax
</textarea></p>
<p><button id="echo">Send ajax request</button></p>
Ajax response: <div id="echo-result"></div>
<p>listedudossier:<p> <?php
foreach ($_['listedudossier'] as $file) {
echo "type:".$file->getType();
echo "<p>";
echo "nom:".$file->getName();
echo "<p>";
echo "modif:".$file->getMTime();
echo "<p>";
}
From here you can test the code in a development environment:
https://github.com/owncloud/ocdev/blob/master/README.rst#installation

Creating Functions in Twig not working

I am attempting to convert some PHP code so that it uses Twig for its template engine.
The code I developed previously worked in such a manner that generating a HTML dropdown list involved calling a static method (formTools::generateSchoolList()) which queried a database and then echo the results into the HTML (spaghetti code).
I've been having some issues creating and then displaying the result of functions and I'm hoping someone can help me troubleshoot the errors I am receiving. In formTools.class.php, I am referring to a single static method for this example and although the Twig Docs suggested using an anonymous method (I called the static function above within the anonymous function), I wasn't able to get that to work, so I made the Twig_SimpleFunction callable parameter the static method directly.
If I do that I get (using return within the static method):
Parse error: syntax error, unexpected '<' in /Path_To_Vendor/vendor/twig/twig/lib/Twig/Environment.php(332) : eval()'d code on line 46
Fatal error: Class '__TwigTemplate_96fa0bd50202e1016defd78dc63d0ee7f8c3432728ffb0946f67a6a1e5c89437' not found in /Path_To_Vendor/vendor/twig/twig/lib/Twig/Environment.php on line 346
If I echo within static function, I get:
Fatal error: Call to undefined method Twig_SimpleFunction::compile() in /path_to_vendor/vendor/twig/twig/lib/Twig/Node/Expression/Call.php on line 27
formTools.class.php
/**
* Generates a list of all available schools in a dropdown box
*
* #throws Exception
*/
static function generateSchoolList() {
$db = new database(databaseHost, databaseUser, databasePass, databaseName);
$query = "SELECT * FROM `schoolCodes`";
$codes = $db->query($query);
if (isset($codes)) {
$result = "<select name='schoolCode'>";
$result .= "<option class='dropdown' value=''> </option>";
$result .= "<option class='dropdown' disabled>----</option>";
foreach ($codes as $code) {
$result .= "<option class='dropdown' value='{$code['codeID']}'>{$code['schoolName']} ({$code['code']})</option>";
}
$result .= "</select>";
**echo/return** $result;
} else {
throw new Exception("The schoolCodes table is empty.");
}
}
formviewer.php
require_once('../vendor/autoload.php');
$ft = new formTools();
$it = new ingestTasks();
Twig_Autoloader::register();
$loader = new Twig_Loader_Filesystem('../templates');
$twig = new Twig_Environment($loader);
$function = new Twig_SimpleFunction('generateSchoolList',
formTools::generateSchoolList()
);
$twig->addFunction($function);
$template = $twig->loadTemplate('viewPlayersByRoster.twig');
echo $twig->render($template);
viewPlayersByRoster.twig
{% extends "base.twig" %}
{% block title %}View Players by Roster{% endblock %}
{% block content %}
<p class="formDesc">This form is for viewing all players on a given roster.</p>
<form action="formviewer.php?action=viewPlayersByRoster" target="_self" method="post">
<input hidden="hidden" value="viewPlayersByRoster" name="action" title="action"/>
<table>
<tr>
<td class="rightAlignText"><label for="schoolCode">School:</label></td>
<td>{{ generateSchoolList() }}</td>
</tr>
</table>
</form>
{% endblock %}
EDIT:
Using PHP 5.5.24 (cannot update past this), Twig 1.18.2 and using Composer.
composer.json
"require": {
"twig/twig": "v1.18.2"
},
"autoload": {
"classmap": ["libs/"]
}
EDIT 2:
Changed to what tacone said and got this:
Catchable fatal error: Object of class __TwigTemplate_96fa0bd50202e1016defd78dc63d0ee7f8c3432728ffb0946f67a6a1e5c89437 could not be converted to string in /path_to_vendor/vendor/twig/twig/lib/Twig/Loader/Filesystem.php on line 216
/Filesystem.php
protected function normalizeName($name)
{
return preg_replace('#/{2,}#', '/', strtr((string) $name, '\\', '/'));
}
formTools.class.php
public function __toString() {
return $this->formTools;
}
You are executing the static method instead of passing its coordinates.
Try using PHP classical callback syntax:
$function = new Twig_SimpleFunction('generateSchoolList', ['formTools', 'generateSchoolList']);
$twig->addFunction($function);
See also https://stackoverflow.com/a/29629460/358813

Zend 2.0: 500 error when creating form element

I am learning Zend Framework (2.0), and I'm stuck at creating forms.
Here is the code I used (Inside a controller):
use Zend\Form\Element;
use Zend\Form\Form;
...
public function indexAction()
{
$element = new Element\Text('name');
//Nothing else
}
It always gives a 505 error, but if I comment out the line "$element ..." then it works (so the problem must be there).
Can someone point out what I have overlooked?
Also, as I see it, there are too many ways to create a form. For example, I have tried:
private function getSignupForm() {
//Create Form
$form = new Zend_Form();
$form->setAction('success');
$form->setMethod('post');
$form->setAttrib('sitename', 'mysite');
//Add Elements
//Create Username Field.
$form->addElement('text', 'username');
$usernameElement = $form->getElement('username');
$usernameElement->setLabel('Username:');
$usernameElement->setOrder(1)->setRequired(true);
return $form;
}
This way, it worked, but that is not the way the tutorial says link. So in which way should I should write it?
Thanks.

Different form formatter for embeded form?

I'm trying to change the form formatter of the embeded form. Is it possible to approach something like this?
class sfOuterForm extends sfForm {
public function configure()
{
$innerForm = new sfForm();
$this->embedForm('inner', $innerForm);
$this->getWidgetSchema()->setFormFormatter('list');
$this->getEmbeddedForm('inner')->getWidgetSchema()->setFormFormatterName('table');
}
}
i'm expecting the following:
echo (new sfOuterForm())
outputs:
<li><label>Outer Label</label><input type="text" /></li>
<li>
<table>
<tr><td><label>Inner Label</label></td><td><input type="text" /></td></tr>
</table>
</li>
Once a form is embedded, it's original widget schema and validator schema do nothing - they've been merged into the top level schemas. Thus, you need to set the form formatter before embedding:
$this->getWidgetSchema()->setFormFormatter('list');
$innerForm = new sfForm();
$innerForm->getWidgetSchema()->setFormFormatterName('table');
$this->embedForm('inner', $innerForm);
It's worth a look into sfForm::embedForm to see what's going on internally.
I'll answer my question by myself :)
The problem arised when i tried to change formatter for relation's embedded forms. I solved this as follows:
class sfOuterForm extends sfForm {
public function configure()
{
$innerForm = new sfForm();
$this->embedRelation('relationName');
$this->getWidgetSchema()->setFormFormatter('list');
$this->getEmbeddedForm('relationName')->getWidgetSchema()->setDefaultFormFormatterName('table');
}
}
Hope this will help someone :)

Categories