Propel - merge collection - collections

Working with Propel ORM 1.5, I'm missing a method to merge two PropelCollections.
A short proposal may be :
public function mergeCollection($collection){
foreach($collection as $i => $item){
if( ! $this->contains($item)){
// append item
$this->append($item);
}
}
}
So I'm new to Propel I would like to ask you, if there are better ways to do it ?
Or is this functionality already included in Propel, but i didn't yet discovered it ?

It seems to have been discuted twice in the mailing list, but I can't find the ticket.
At least, you can try this code and/or open a ticket on Github.
/**
* Add a collection of elements, preventing duplicates
*
* #param array $collection The collection
*
* #return int the number of new element in the collection
*/
public function addCollection($collection)
{
$i = 0;
foreach($collection as $ref) {
if ($this->add($ref)) {
$i = $i + 1;
}
}
return $i;
}
/**
* Add a an element to the collection, preventing duplicates
*
* #param $element The element
*
* #return bool if the element was added or not
*/
public function add($element)
{
if ($element != NULL) {
if ($this->isEmpty()) {
$this->append($element);
return true;
} else if (!$this->contains($element)) {
set_error_handler("error_2_exception");
try {
if (!method_exists($element, 'getPrimaryKey')) {
restore_error_handler();
$this->append($element);
return true;
}
if ($this->get($element->getPrimaryKey()) != null) {
restore_error_handler();
return false;
} else {
$this->append($element);
restore_error_handler();
return true;
}
} catch (Exception $x) {
//il semble que l'element ne soit pas dans la collection
restore_error_handler(); //restore the old handler
$this->append($element);
return true;
}
restore_error_handler(); //restore the old handler
}
}
return false;
}
}
function error_2_exception($errno, $errstr, $errfile, $errline,$context) {
throw new Exception('',$errno);
return true;
}

Related

Vies VAT Validator checkout WooCommerce

does anyone know this plugin for VAT validation? https://wordpress.org/plugins/vies-validator/
Here is the explanation of the library used: https://github.com/pH-7/eu-vat-validator
It works very well, also because in my case I already have the VAT number as a field, and therefore, since it allows you to assign the ID to the panel of your existing field, it validates it.
However, I would like to exclude Italy from validation, inside the plugin I see the 3 functions that validate the VAT number, but I can't understand how to exclude the country I want.
/**
* Validate the VAT Number
*
* #since 1.0.0
*/
public function vies_validator_validate_vat() {
$enable_vat = get_option($this->option_name . '_add_vat_field');
if ($enable_vat && $enable_vat == 1) {
$vat_id = 'vies_billing_vat';
}
else {
$vat_id = get_option($this->option_name . '_vat_id');
}
if ($vat_id && !empty(trim($vat_id))) {
$this->vies_validator_validate_vat_field($vat_id);
}
}
/**
* Check a VAT Number via API
*
* #since 1.0.0
*/
protected function vatCheck($vat_number) {
$country = substr($vat_number, 0, 2);
try {
$oVatValidator = new Validator(new Europa, $vat_number, $country);
return $oVatValidator->check();
}
catch (Exception $e) {
return false;
}
}
/**
* Validates vat number
*
* #since 1.0.0
*/
protected function vies_validator_validate_vat_field($vat_id) {
if(isset($_POST[$vat_id]) && !empty($_POST[$vat_id])) {
$vat_number = $_POST[$vat_id];
if (! $this->vatCheck($vat_number)) {
wc_add_notice(__(get_option('vies_validator_message'), 'vies-validator'), 'error');
}
}
}
}
Only the functions are protected and public and I don't understand how to call a hook to make the function run in WordPress functions.php.
Here, I see the hooks being logged and there is the WooCommerce checkout hook.
/**
* Register all of the hooks related to the public-facing
functionality
* of the plugin.
*
* #since 1.0.0
* #access private
*/
private function define_public_hooks() {
$plugin_public = new Vies_Validator_Public( $this->get_plugin_name(), $this->get_version() );
$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' );
$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
if (get_option('vies_validator_add_vat_field') == '1') {
$this->loader->add_filter('woocommerce_billing_fields', $plugin_public, 'vies_validator_add_vat_field', 10, 1);
$this->loader->add_filter( 'woocommerce_my_account_my_address_formatted_address', $plugin_public, 'vies_my_account_my_address_formatted_address', 10, 3 );
$this->loader->add_filter( 'woocommerce_order_formatted_billing_address', $plugin_public, 'vies_add_vat_formatted_billing_address', 10, 2 );
$this->loader->add_filter( 'woocommerce_formatted_address_replacements', $plugin_public, 'vies_formatted_address_replacements', 10, 2 );
$this->loader->add_filter( 'woocommerce_customer_meta_fields', $plugin_public, 'vies_customer_meta_fields' );
$this->loader->add_filter( 'woocommerce_admin_billing_fields', $plugin_public, 'vies_admin_billing_fields' );
$this->loader->add_filter( 'woocommerce_found_customer_details', $plugin_public, 'vies_found_customer_details' );
}
$this->loader->add_action('woocommerce_checkout_process', $plugin_public, 'vies_validator_validate_vat');
}
Thanks
If you just want the code to accept all Italian VAT numbers then you can just make a small modification to the vat check function:
protected function vatCheck($vat_number) {
$country = substr($vat_number, 0, 2);
if ($country == 'IT' || $country == 'it') {
return true;
} else {
try {
$oVatValidator = new Validator(new Europa, $vat_number, $country);
return $oVatValidator->check();
}
catch (Exception $e) {
return false;
}
}
}
If you want the code to reject all Italian numbers then use this version:
protected function vatCheck($vat_number) {
$country = substr($vat_number, 0, 2);
if ($country == 'IT' || $country == 'it') {
return false;
} else {
try {
$oVatValidator = new Validator(new Europa, $vat_number, $country);
return $oVatValidator->check();
}
catch (Exception $e) {
return false;
}
}
}
Good luck. I hope it will work for you. If not then you might find this VAT Validation Add-in that works with directly within Excel and can do bulk VAT validation: https://www.sanocast.dk/vat-validation/
It is fantastic! (I might be a little biased - it is my own creation)

#Security("is_granted('remove', user)") uses not request user, symfony2

When I use the annotation #Security("is_granted('remove', user)"), I get a wrong user in Voter
/**
* Delete User by ID
*
* #Rest\Delete("/{id}", name="delete_user")
* #Security("is_granted('remove', user)")
*
* #ApiDoc(
* section="5. Users",
* resource=true,
* description="Delete User",
* headers={
* {
* "name"="Authorization: Bearer [ACCESS_TOKEN]",
* "description"="Authorization key",
* "required"=true
* }
* },
* requirements={
* {
* "name"="id",
* "dataType"="string",
* "requirement"="\[a-z\-]+",
* "description"="Id of the object to receive"
* }
* },
* output="Status"
* )
*
* #param User $user
* #return Response;
*/
public function deleteAction(User $user)
{
//$this->denyAccessUnlessGranted('remove', $user);
$em = $this->getDoctrine()->getManager();
$em->remove($user);
$em->flush();
$view = $this->view('Success deleted', Response::HTTP_NO_CONTENT);
return $this->handleView($view);
}
But, if I use functions in the body $this->denyAccessUnlessGranted('remove', $user);, it's all right. Help me to understand...
Settings
services:
user.user_voter:
class: OD\UserBundle\Security\UserVoter
arguments: ['#security.access.decision_manager']
public: false
tags:
- { name: security.voter }
Voter
namespace OD\UserBundle\Security;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use OD\UserBundle\Entity\User;
class UserVoter extends Voter
{
const VIEW = 'view';
const EDIT = 'edit';
const REMOVE = 'remove';
protected function supports($attribute, $subject)
{
# if the attribute isn't one we support, return false
if (!in_array($attribute, array(self::VIEW, self::EDIT, self::REMOVE))) {
return false;
}
# only vote on Booking objects inside this voter
if (!$subject instanceof User) {
return false;
}
return true;
}
protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
$user = $token->getUser();
if (!$user instanceof User) {
# the user must be logged in; if not, deny access
return false;
}
switch ($attribute) {
case self::VIEW:
return $this->canView($subject, $user);
case self::EDIT:
return $this->canEdit($subject, $user);
case self::REMOVE:
return $this->canRemove($subject, $user);
}
throw new \LogicException('This code should not be reached!');
}
private function canView(User $subject, User $user)
{
if ($subject->getId() === $user->getId()) {
return true;
}
return false;
}
private function canEdit(User $subject, User $user)
{
if ($subject->getId() === $user->getId()) {
return true;
}
return false;
}
private function canRemove(User $subject, User $user)
{
if ($subject->getId() === $user->getId()) {
return true;
}
return false;
}
}
* #Security("is_granted('remove', removingUser)")
* #param User $removingUser
* #return Response;
*/
public function deleteAction(User $removingUser)
This code works well. This code works well. I did not find the confirmation, but it seems the user is reserved for the current user

Symfony Two edit actions (activate/desactivate) one is working and the other doesn't work

I have two actions that edit the entity 'user' attribute 'etat' : activateAction makes the 'etat' equals to 1 if it was equal to 0, else it returns a flashbag message 'the account is already activated', and the desactivateAction is supposed to do the opposite, but it doesn't work!!! Here is the code of both activate and desactivate actions:
/**
* #Route("/admin/gestEtat/act/{iduser}", name="act")
*
* #Template()
*/
public function activateAction($iduser)
{
$user=new user();
$em=$this->getDoctrine()->getManager();
$repository = $em->getRepository("CNAMCMSBundle:user");
$user = $repository->find($iduser);
if($user)
{
if ($user->getEtat()==1) {
$this->get("session")->getFlashBag()->add('act',"Ce compte est déjà activé!");
return $this->redirectToRoute('gestEtat',
array());
}
elseif ($user->getEtat()==0) {
$user->setEtat('1');
$em->merge($user);
$em->flush();
return $this->redirectToRoute('gestEtat',
array());
}
}
}
/**
* #Route("/admin/gestEtat/desact/{id}",name="desact")
*
* #Template()
*/
public function desactivateAction($id)
{
$user=new user();
$em=$this->getDoctrine()->getManager();
$repository = $em->getRepository("CNAMCMSBundle:user");
$user = $repository->find($id);
//$session = new Session();
//$session->start();
//$users=$session->get('users_table');
if($user)
{
if ($user->getEtat()==0) {
$this->get("session")->getFlashBag()->add('desact',"Ce compte est déjà désactivé!");
// return $this->render('CNAMCMSBundle:Default:gestEtat.html.twig',
return $this->redirectToRoute('gestEtat',
array());
}
elseif ($user->getEtat()==1) {
$user->setEtat('0');
$em->merge($user);
$em->flush();
// return $this->render('CNAMCMSBundle:Default:gestEtat.html.twig',
return $this->redirectToRoute('gestEtat',
array());
}
}
}
Seems like you're performing setEtat('0') by passing in the string '0'. If the entity variable is a boolean, you should send it as a (true/false) or (1/0). If it is a string, you should be checking in your code elseif (getEtat()=='1')
The way it stands, checking if (getEtat()==1) will be the same as if (getEtat()), which will return true if getEtat() is not explicitly a false/null boolean, or a null variable.

Property is not flushed

I call a service in a controller:
$this->getContainer()->get('pro_convocation')->sendDelegationEmails();
Here it is the method executed with the service:
function sendDelegationEmails()
{
foreach ($this->getRepository()->findWithPendingDelegationsEmail(1) as $convocation) {
if (! $convocation->delegationsEmailCanBeSent()) continue;
$this->sendDelegationsEmails($convocation);
$convocation->_setDelegationsEmailIsSent(); //<--- it is not saved
$this->save($convocation);
}
}
and the other used methods in the same class:
/**
* #return \Pro\ConvocationBundle\Entity\ConvocationRepository
*/
private function getRepository()
{
return $this->get('doctrine')->getRepository('ProConvocationBundle:Convocation');
}
function save(ConvocationEntity $convocation)
{
$this->getEntityManager()->persist($convocation);
$this->getEntityManager()->flush();
}
function sendDefinitiveMinute(ConvocationEntity $convocation)
{
foreach ($convocation->getCommunity()->getMembers() as $user) {
$this->get('pro.notifications')->send(Notification::create()
...
->setBody($this->get('templating')->render(
'ProConvocationBundle:Convocation:definitive-minute.html.twig',
array(
'convocation' => $convocation,
'convocationIsOrdinary' => $this->get('pro_convocation.ordinariness')->isOrdinary($convocation),
'user' => $user
)
))
);
}
}
EDIT: The send method:
function send(Notification $notification)
{
if (! $notification->getRecipient()) throw new \Exception("Recipient not set");
if (! $notification->getRecipient()->getEmail()) {
$this->logger->info(sprintf(
"Notification \"%s\" ignored as recipient %s has no email",
$notification->getSubject(), $notification->getRecipient()));
return;
}
// Ignore notifications to the own author
if ($notification->getAuthor() === $notification->getRecipient()) {
$this->logger->info(sprintf(
"Notification ignored as recipient is the author (%s)",
$notification->getRecipient()));
return;
}
$em = $this->doctrine->getManager();
$em->persist($notification);
$em->flush();
if ($this->notificationHasToBeMailed($notification)) {
$this->mail($notification);
$this->logger->info("Notification mailed to {$notification->getRecipient()}");
}
}
END EDIT
The _setDelegationsEmailIsSent method and delegationsEmailIsSent property in the Convocation entity:
/**
* #ORM\Column(type="boolean", name="delegations_email_is_sent")
* #Constraints\NotNull
*/
private $delegationsEmailIsSent = false;
/**
* #internal
* #see \Pro\ConvocationBundle\Convocation::sendDelegationsEmails()
*/
function _setDelegationsEmailIsSent()
{
$this->delegationsEmailIsSent = true;
}
The problem is that delegations_email_is_sent in the database is not changing to true when executing the sendDelegationEmails method in a controller. I've tried several changes without success. It seems to be related to flush method, but I don't find the issue.

Finding out what changed via postUpdate listener in Symfony 2.1

I have a postUpdate listener and I'd like to know what the values were prior to the update and what the values for the DB entry were after the update. Is there a way to do this in Symfony 2.1? I've looked at what's stored in getUnitOfWork() but it's empty since the update has already taken place.
You can use this ansfer Symfony2 - Doctrine - no changeset in post update
/**
* #param LifecycleEventArgs $args
*/
public function postUpdate(LifecycleEventArgs $args)
{
$changeArray = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($args->getObject());
}
Found the solution here. What I needed was actually part of preUpdate(). I needed to call getEntityChangeSet() on the LifecycleEventArgs.
My code:
public function preUpdate(Event\LifecycleEventArgs $eventArgs)
{
$changeArray = $eventArgs->getEntityChangeSet();
//do stuff with the change array
}
Your Entitiy:
/**
* Order
*
* #ORM\Table(name="order")
* #ORM\Entity()
* #ORM\EntityListeners(
* {"\EventListeners\OrderListener"}
* )
*/
class Order
{
...
Your listener:
class OrderListener
{
protected $needsFlush = false;
protected $fields = false;
public function preUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
return $this->setFields($entity, $eventArgs);
}
public function postUpdate($entity, LifecycleEventArgs $eventArgs)
{
if (!$this->isCorrectObject($entity)) {
return null;
}
foreach ($this->fields as $field => $detail) {
echo $field. ' was ' . $detail[0]
. ' and is now ' . $detail[1];
//this is where you would save something
}
$eventArgs->getEntityManager()->flush();
return true;
}
public function setFields($entity, LifecycleEventArgs $eventArgs)
{
$this->fields = array_diff_key(
$eventArgs->getEntityChangeSet(),
[ 'modified'=>0 ]
);
return true;
}
public function isCorrectObject($entity)
{
return $entity instanceof Order;
}
}
You can find example in doctrine documentation.
class NeverAliceOnlyBobListener
{
public function preUpdate(PreUpdateEventArgs $eventArgs)
{
if ($eventArgs->getEntity() instanceof User) {
if ($eventArgs->hasChangedField('name') && $eventArgs->getNewValue('name') == 'Alice') {
$eventArgs->setNewValue('name', 'Bob');
}
}
}
}

Resources