Skip to content

Commit

Permalink
[DomCrawler] added the component
Browse files Browse the repository at this point in the history
  • Loading branch information
fabpot committed Apr 15, 2010
1 parent 13759a7 commit 7973271
Show file tree
Hide file tree
Showing 17 changed files with 3,011 additions and 0 deletions.
640 changes: 640 additions & 0 deletions src/Symfony/Components/DomCrawler/Crawler.php

Large diffs are not rendered by default.

208 changes: 208 additions & 0 deletions src/Symfony/Components/DomCrawler/Field/ChoiceFormField.php
@@ -0,0 +1,208 @@
<?php

namespace Symfony\Components\DomCrawler\Field;

/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* ChoiceFormField represents a choice form field.
*
* It is constructed from a HTML select tag, or a HTML checkbox, or radio inputs.
*
* @package Symfony
* @subpackage Components_DomCrawler
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class ChoiceFormField extends FormField
{
protected $type;
protected $multiple;
protected $options;

/**
* Returns true if the field should be included in the submitted values.
*
* @return Boolean true if the field should be included in the submitted values, false otherwise
*/
public function hasValue()
{
// don't send a value for unchecked checkboxes
if (in_array($this->type, array('checkbox', 'radio')) && null === $this->value)
{
return false;
}

return true;
}

/**
* Sets the value of the field.
*
* @param string $value The value of the field
*/
public function setValue($value)
{
if ('checkbox' == $this->type && false === $value)
{
// uncheck
$this->value = null;
}
elseif ('checkbox' == $this->type && true === $value)
{
// check
$this->value = $this->options[0];
}
else
{
if (is_array($value))
{
if (!$this->multiple)
{
throw new \InvalidArgumentException(sprintf('The value for "%s" cannot be an array.', $this->name));
}

foreach ($value as $v)
{
if (!in_array($v, $this->options))
{
throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $v, implode(', ', $this->options)));
}
}
}
elseif (!in_array($value, $this->options))
{
throw new \InvalidArgumentException(sprintf('Input "%s" cannot take "%s" as a value (possible values: %s).', $this->name, $value, implode(', ', $this->options)));
}

if ($this->multiple && !is_array($value))
{
$value = array($value);
}

if (is_array($value))
{
$this->value = $value;
}
else
{
parent::setValue($value);
}
}
}

/**
* Adds a choice to the current ones.
*
* This method should only be used internally.
*
* @param \DOMNode $node A \DOMNode
*/
public function addChoice(\DOMNode $node)
{
if (!$this->multiple && 'radio' != $this->type)
{
throw new \LogicException(sprintf('Unable to add a choice for "%s" as it is not multiple or is not a radio button.', $this->name));
}

$this->options[] = $value = $node->hasAttribute('value') ? $node->getAttribute('value') : '1';

if ($node->getAttribute('checked'))
{
$this->value = $value;
}
}

/**
* Returns the type of the choice field (radio, select, or checkbox).
*
* @return string The type
*/
public function getType()
{
return $this->type;
}

/**
* Returns true if the field accepts multiple values.
*
* @return Boolean true if the field accepts multiple values, false otherwise
*/
public function isMultiple()
{
return $this->multiple;
}

/**
* Initializes the form field.
*/
protected function initialize()
{
if ('input' != $this->node->nodeName && 'select' != $this->node->nodeName)
{
throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input or select tag (%s given).', $this->node->nodeName));
}

if ('input' == $this->node->nodeName && 'checkbox' != $this->node->getAttribute('type') && 'radio' != $this->node->getAttribute('type'))
{
throw new \LogicException(sprintf('A ChoiceFormField can only be created from an input tag with a type of checkbox or radio (given type is %s).', $this->node->getAttribute('type')));
}

$this->value = null;
$this->options = array();
$this->multiple = false;

if ('input' == $this->node->nodeName)
{
$this->type = $this->node->getAttribute('type');
$this->options[] = $value = $this->node->hasAttribute('value') ? $this->node->getAttribute('value') : '1';

if ($this->node->getAttribute('checked'))
{
$this->value = $value;
}
}
else
{
$this->type = 'select';
if ($this->node->hasAttribute('multiple'))
{
$this->multiple = true;
$this->value = array();
$this->name = str_replace('[]', '', $this->name);
}

$found = false;
foreach ($this->xpath->query('descendant::option', $this->node) as $option)
{
$this->options[] = $option->getAttribute('value');

if ($option->getAttribute('selected'))
{
$found = true;
if ($this->multiple)
{
$this->value[] = $option->getAttribute('value');
}
else
{
$this->value = $option->getAttribute('value');
}
}
}

// if no option is selected and if it is a simple select box, take the first option as the value
$option = $this->xpath->query('descendant::option', $this->node)->item(0);
if (!$found && !$this->multiple && $option instanceof \DOMElement)
{
$this->value = $option->getAttribute('value');
}
}
}
}
78 changes: 78 additions & 0 deletions src/Symfony/Components/DomCrawler/Field/FileFormField.php
@@ -0,0 +1,78 @@
<?php

namespace Symfony\Components\DomCrawler\Field;

/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* FileFormField represents a file form field (an HTML file input tag).
*
* @package Symfony
* @subpackage Components_DomCrawler
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
class FileFormField extends FormField
{
/**
* Sets the PHP error code associated with the field.
*
* @param integer $error The error code (one of UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, or UPLOAD_ERR_EXTENSION)
*/
public function setErrorCode($error)
{
$codes = array(UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_EXTENSION);
if (!in_array($error, $codes))
{
throw new \InvalidArgumentException(sprintf('The error code %s is not valid.', $error));
}

$this->value = array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => $error, 'size' => 0);
}

/**
* Sets the value of the field.
*
* @param string $value The value of the field
*/
public function setValue($value)
{
if (null !== $value && is_readable($value))
{
$error = UPLOAD_ERR_OK;
$size = filesize($value);
}
else
{
$error = UPLOAD_ERR_NO_FILE;
$size = 0;
$value = '';
}

$this->value = array('name' => basename($value), 'type' => '', 'tmp_name' => $value, 'error' => $error, 'size' => $size);
}

/**
* Initializes the form field.
*/
protected function initialize()
{
if ('input' != $this->node->nodeName)
{
throw new \LogicException(sprintf('A FileFormField can only be created from an input tag (%s given).', $this->node->nodeName));
}

if ('file' != $this->node->getAttribute('type'))
{
throw new \LogicException(sprintf('A FileFormField can only be created from an input tag with a type of file (given type is %s).', $this->node->getAttribute('type')));
}

$this->setValue(null);
}
}
93 changes: 93 additions & 0 deletions src/Symfony/Components/DomCrawler/Field/FormField.php
@@ -0,0 +1,93 @@
<?php

namespace Symfony\Components\DomCrawler\Field;

/*
* This file is part of the symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/**
* FormField is the abstract class for all form fields.
*
* @package Symfony
* @subpackage Components_DomCrawler
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
*/
abstract class FormField
{
protected $node;
protected $name;
protected $value;
protected $document;
protected $xpath;

/**
* Constructor.
*
* @param \DOMNode $node The node associated with this field
*/
public function __construct(\DOMNode $node)
{
$this->node = $node;
$this->name = $node->getAttribute('name');

$this->document = new \DOMDocument('1.0', 'UTF-8');
$this->node = $this->document->importNode($this->node, true);

$root = $this->document->appendChild($this->document->createElement('_root'));
$root->appendChild($this->node);
$this->xpath = new \DOMXPath($this->document);

$this->initialize();
}

/**
* Returns the name of the field.
*
* @return string The name of the field
*/
public function getName()
{
return $this->name;
}

/**
* Gets the value of the field.
*
* @return string|array The value of the field
*/
public function getValue()
{
return $this->value;
}

/**
* Sets the value of the field.
*
* @param string $value The value of the field
*/
public function setValue($value)
{
$this->value = (string) $value;
}

/**
* Returns true if the field should be included in the submitted values.
*
* @return Boolean true if the field should be included in the submitted values, false otherwise
*/
public function hasValue()
{
return true;
}

/**
* Initializes the form field.
*/
abstract protected function initialize();
}

0 comments on commit 7973271

Please sign in to comment.