On new node create , Drupal is giving error message "The file used in the Image field may not be referenced." - drupal-7

When I am gong to create a new node of a type , then upload the image field , its showing an error "The file used in the Image field may not be referenced.". I have implemented the hook_file_insert function in which it was told to use file_usage_add. I have my code below:
function mymodule_file_insert($file){
if($file->source=="field_image_und_0" || $file->source=="field_twitter_image_und_0"){
mymodule_manage_file($file);
}
}
/**
* implements file manage
*/
function mymodule_manage_file($file){
if($file->fid){
mymodule_save_file($file->fid);
}
}
/**
* implements save file
*/
function mymodule_save_file($file_id){
$file = file_load($file_id);
$file->status = FILE_STATUS_PERMANENT;
file_save($file);
file_usage_add($file, 'file', 'node', $nid);
}
Here I get here the nid when new node is creating?

Your are passing the $nid, and it has not value. I think this should works:
function mymodule_file_insert($file){
if($file->source=="field_image_und_0" || $file->source=="field_twitter_image_und_0"){
mymodule_manage_file($file);
}
}
/**
* implements file manage
*/
function mymodule_manage_file($file){
if($file->fid){
mymodule_save_file($file->fid);
}
}
/**
* implements save file
*/
function mymodule_save_file($file_id, $nid){
$file = file_load($file_id);
if (isset($nid)) {
file_usage_add($file, 'file', 'node', $nid);
}else {
$file->status = FILE_STATUS_PERMANENT;
file_save($file);
}
}
/**
* Implements hook_node_insert().
*/
function mymodule_node_insert($node) {
mymodule_save_file($node->field_name[LANGUAGE_NONE][0]['fid'],
$node->nid);
}

Related

CakePHP 4.2 Annotate: incorrect app namespace

I'm using CakePHP version 4.2 and am noticing some odd behavior from the annotate script that comes bundled with the API. For one component, the annotate script wants to default to the App\ domain that is CakePHP's default. I've changed the application name so most other classes default to the correct application name. But not this one script and so far, only for this one file.
I've included the body of the component, for review, below. You can see that the #method annotation uses the App\ domain. The trouble comes in when I use PHPStan to analyze my code. If I leave the annotation as is, PHPStan will tell me:
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
Line src/Controller/Component/CartManagerComponent.php
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
43 Property Visualize\Controller\Component\CartManagerComponent::$Controller (Visualize\Controller\AppController) does not accept App\Controller\AppController.
44 Call to method loadModel() on an unknown class App\Controller\AppController.
💡 Learn more at https://phpstan.org/user-guide/discovering-symbols
------ --------------------------------------------------------------------------------------------------------------------------------------------------------------
The file itself doesn't use the App\ domain anywhere. I'm not sure where to look for the script to figure out whats wrong. Here is the body of my component in case you see something I do not:
<?php
declare(strict_types=1);
namespace Visualize\Controller\Component;
use Authorization\Identity;
use Cake\Controller\Component;
use Cake\Log\Log;
/**
* CartManager component
*
* #method \App\Controller\AppController getController()
* #property \Visualize\Controller\AppController $Controller
* #property \Visualize\Model\Table\CartsTable $Carts
*/
class CartManagerComponent extends Component
{
/**
* Default configuration.
*
* #var array
*/
protected $_defaultConfig = [];
/**
* #var \Visualize\Controller\AppController
*/
protected $Controller;
/**
* #var \Visualize\Model\Table\CartsTable
*/
protected $Carts;
/**
* #param array $config The current configuration array
* #return void
*/
public function initialize(array $config): void
{
parent::initialize($config);
$this->Controller = $this->getController();
$this->Controller->loadModel('Carts');
}
/**
* Returns the most recent active cart.
*
* #param \Authorization\Identity $user The User entity.
* #return array|\Cake\Datasource\EntityInterface|null
* #noinspection PhpUnnecessaryFullyQualifiedNameInspection
*/
public function getUserCart(Identity $user)
{
$cart = $this->Controller->Carts->newEmptyEntity();
if (!empty($this->Controller->Carts) && is_a($this->Controller->Carts, '\Visualize\Model\Table\CartsTable')) {
$query = $this->Controller->Carts->find('userCart', ['user_id' => $user->getIdentifier()]);
if (!$query->isEmpty()) {
$cart = $query->first();
} else {
$cart->set('user_id', $user->getIdentifier());
$this->Controller->Carts->save($cart);
}
if (is_object($cart) && is_a($cart, '\Cake\Datasource\EntityInterface')) {
$session = $this->Controller->getRequest()->getSession();
$session->write('Cart.id', $cart->id);
}
}
return $cart;
}
/**
* Abandons carts
*
* #param int $user_id The associated user ID
* #param int $cart_id The current cart ID
* #return void
*/
public function pruneCarts(int $user_id, int $cart_id): void
{
if (!empty($this->Controller->Carts) && is_a($this->Controller->Carts, '\Visualize\Model\Table\CartsTable')) {
// Find all the carts we didn't just create:
$userCarts = $this->Controller->Carts->find('all', ['fields' => ['id', 'user_id', 'cart_status']])
->where([
'id !=' => $cart_id,
'user_id' => $user_id,
'cart_status' => 'active',
]);
if (!$userCarts->isEmpty()) {
$count = 0;
foreach ($userCarts as $cart) {
if ($count < 5) {
$record = $this->Controller->Carts->newEmptyEntity();
$record = $this->Controller->Carts->patchEntity($record, $cart->toArray());
$record->set('id', $cart->id);
$record->set('cart_status', ABANDONED_CART);
if (!$this->Controller->Carts->save($record)) {
Log::alert('Error abandoning cart');
}
} else {
$this->Controller->Carts->delete($cart);
}
$count++;
}
}
}
}
}

Fatal error: Declaration of CRMCoreContactController::save($contact) must be compatible with EntityAPIController::save

I recently installed CRM Core and all of its missing modules needed to run it. Sadly I need this module for the project that I am working on but the second I installed them I got this error.
Fatal error: Declaration of CRMCoreContactController::save($contact) must be compatible with EntityAPIController::save($entity, ?DatabaseTransaction $transaction = NULL) in /opt/lampp/htdocs/drupal/modules/crm_core/modules/crm_core_contact/includes/crm_core_contact.controller.inc on line 111
I went back in the code and I couldn't see what to change. Line 111 is the ver last line of the code. Ill paste the code as well maybe someone out there knows how to solve this, please.
<?php
/**
* CRM Contact Entity Class.
*/
class CRMCoreContactEntity extends Entity {
protected function defaultLabel() {
return crm_core_contact_label($this);
}
protected function defaultUri() {
return array(
'path' => 'crm-core/contact/' . $this->identifier(),
'options' => array(
'absolute' => TRUE,
),
);
}
/**
* Method for de-duplicating contacts.
*
* Allows various modules to identify duplicate contact records through
* hook_crm_core_contact_match. This function should implement it's
* own contact matching scheme.
*
* #return array
* Array of matched contact IDs.
*/
public function match() {
$checks = & drupal_static(__FUNCTION__);
$matches = array();
if (!isset($checks->processed)) {
$checks = new stdClass();
$checks->engines = module_implements('crm_core_contact_match');
$checks->processed = 1;
}
// Pass in the contact and the matches array as references.
// This will allow various matching tools to modify the contact
// and the list of matches.
$values = array(
'contact' => &$this,
'matches' => &$matches,
);
foreach ($checks->engines as $module) {
module_invoke($module, 'crm_core_contact_match', $values);
}
// It's up to implementing modules to handle the matching logic.
// Most often, the match to be used should be the one
// at the top of the stack.
return $matches;
}
}
/**
* #file
* Controller class for contacts.
*
* This extends the DrupalDefaultEntityController class, adding required
* special handling for contact objects.
*/
class CRMCoreContactController extends EntityAPIController {
public $revisionKey = 'vid';
public $revisionTable = 'crm_core_contact_revision';
/**
* Create a basic contact object.
*/
public function create(array $values = array()) {
global $user;
$values += array(
'contact_id' => '',
'vid' => '',
'uid' => $user->uid,
'created' => REQUEST_TIME,
'changed' => REQUEST_TIME,
);
return parent::create($values);
}
/**
* Update contact object before saving revision.
*/
protected function saveRevision($entity) {
if (!isset($entity->log)) {
$entity->log = '';
}
$entity->is_new_revision = TRUE;
$entity->uid = $GLOBALS['user']->uid;
return parent::saveRevision($entity);
}
/**
* Updates 'changed' property on save.
*/
public function save($contact) {
$contact->changed = REQUEST_TIME;
// Storing formatted contact label for autocomplete lookups.
$contact->name = crm_core_contact_label($contact);
return parent::save($contact);
}
}
Changing
public function save($contact)
to
public function save($contact, DatabaseTransaction $transaction = NULL)
should work.
You need to switch from PHP 7.x+ to PHP 5.6. This will resolve this error.
Can't give you more advice on how to downgrade without more details on what system you're running but there are many guides out there on this topic.

Bypass spool when using thirdparty database spooling

I'm using a thirdparty bundle (Dextervip Citrax\DatabaseSwiftmailerBundle) to spool my email in a database. However, I still want to be able to bypass the spooling for some specific actions. Before, when I didn't use the bundle and used just regular spooling, I did this the following way:
public function sendSeparateMessage($subject, $fromEmail, $toEmail, $toCc, $body, $bypassSpool = false){
$message = \Swift_Message::newInstance()
->setSubject($subject)
->setFrom($fromEmail)
->setTo($toEmail)
->setCc($toCc)
->setBody($body)
->setContentType("text/html");
// Send the message
$failedRecipients = [];
$numSent = 0;
foreach ($toEmail as $address => $name)
{
if (is_int($address)) {
$toEmail = $message->setTo($name);
} else {
$toEmail = $message->setTo([$address => $name]);
}
$numSent += $this->mailer->send($message, $failedRecipients);
}
if($bypassSpool) {
$spool = $this->mailer->getTransport()->getSpool();
$transport = \Swift_MailTransport::newInstance();
$spool->flushQueue($transport);
}
}
So whenever the last parameter of that function was set to true, the emails got sent out immediately and weren't stored for spooling.
For my situation now, I'd like to have the same thing, but of course I'm calling the wrong flushQueue function because I'm probably not accessing the right spooler. Does anybody know how to access the spooler from that bundle?
The service class from that bundle:
<?php
/**
* Created by PhpStorm.
* User: Rafael
* Date: 02/05/2015
* Time: 22:16
*/
namespace Citrax\Bundle\DatabaseSwiftMailerBundle\Spool;
use Citrax\Bundle\DatabaseSwiftMailerBundle\Entity\Email;
use Citrax\Bundle\DatabaseSwiftMailerBundle\Entity\EmailRepository;
use Swift_Mime_Message;
use Swift_Transport;
class DatabaseSpool extends \Swift_ConfigurableSpool {
/**
* #var EmailRepository
*/
private $repository;
private $parameters;
public function __construct(EmailRepository $repository, $parameters)
{
$this->repository = $repository;
$this->parameters = $parameters;
}
/**
* Starts this Spool mechanism.
*/
public function start()
{
// TODO: Implement start() method.
}
/**
* Stops this Spool mechanism.
*/
public function stop()
{
// TODO: Implement stop() method.
}
/**
* Tests if this Spool mechanism has started.
*
* #return bool
*/
public function isStarted()
{
return true;
}
/**
* Queues a message.
*
* #param Swift_Mime_Message $message The message to store
*
* #return bool Whether the operation has succeeded
*/
public function queueMessage(Swift_Mime_Message $message)
{
$email = new Email();
$email->setFromEmail(implode('; ', array_keys($message->getFrom())) );
if($message->getTo() !== null ){
$email->setToEmail(implode('; ', array_keys($message->getTo())) );
}
if($message->getCc() !== null ){
$email->setCcEmail(implode('; ', array_keys($message->getCc())) );
}
if($message->getBcc() !== null ){
$email->setBccEmail(implode('; ', array_keys($message->getBcc())) );
}
if($message->getReplyTo() !== null ){
$email->setReplyToEmail(implode('; ', array_keys($message->getReplyTo())) );
}
$email->setBody($message->getBody());
$email->setSubject($message->getSubject());
$email->setMessage($message);
$this->repository->addEmail($email);
}
/**
* Sends messages using the given transport instance.
*
* #param Swift_Transport $transport A transport instance
* #param string[] $failedRecipients An array of failures by-reference
*
* #return int The number of sent emails
*/
public function flushQueue(Swift_Transport $transport, &$failedRecipients = null)
{
if (!$transport->isStarted())
{
$transport->start();
}
$count = 0;
$emails = $this->repository->getEmailQueue($this->getMessageLimit());
foreach($emails as $email){
/*#var $message \Swift_Mime_Message */
$message = $email->getMessage();
try{
$count_= $transport->send($message, $failedRecipients);
if($count_ > 0){
$this->repository->markCompleteSending($email);
$count += $count_;
}else{
throw new \Swift_SwiftException('The email was not sent.');
}
}catch(\Swift_SwiftException $ex){
$this->repository->markFailedSending($email, $ex);
}
}
return $count;
}
}
and the services.yml file:
services:
repository.email:
class: Citrax\Bundle\DatabaseSwiftMailerBundle\Entity\EmailRepository
factory: ['#doctrine.orm.default_entity_manager',getRepository]
arguments: ['CitraxDatabaseSwiftMailerBundle:Email']
citrax.database.swift_mailer.spool:
class: Citrax\Bundle\DatabaseSwiftMailerBundle\Spool\DatabaseSpool
arguments: ['#repository.email', '%citrax_database_swift_mailer.params%']
swiftmailer.spool.db:
alias: citrax.database.swift_mailer.spool
swiftmailer.mailer.default.spool.db:
alias: citrax.database.swift_mailer.spool

Doctrine searching on Entity without any filters

I was wondering if there is a way to search in entity without applying any filters. For Example I would like to build a textfiled in my template where a ajax post method is calling to a controller with purpose searching the whole entity.
My code:
$user = $this->getDoctrine()
->getRepository('AppBundle:QCE_SUBD')
->find('%'.$SearchParam.'%')
->getQuery();
$DSUB = $user->getArrayResult();
dump($DSUB);
I;m not sure how the function should be written, so if some one is willing to help it will be highly appreciate :)
You should just create a function that return a JsonResponse with an array of your result.
// In your controller
/**
* #Route("/ajax_action")
*/
public function ajaxAction(Request $request)
{
// Get the posted parameter from your ajax call
$searchParam = $request->get('searchParam');
// Request your entity
$user = $this->getDoctrine()
->getRepository('AppBundle:QCE_SUBD')
->createQueryBuilder('q')
->where('q.username LIKE :searchParam')
->orWhere('q.otherColumn LIKE :searchParam')
->setParameter('searchParam', '%'.$searchParam.'%')
->getQuery();
// Check if it's an ajax call
if ($request->isXMLHttpRequest()) {
return new JsonResponse($user->getArrayResult();
}
// Return an error
throw new \Exception('Wrong call!');
}
For the search part you need to implement a full text search, here is a tutorial on how to implement it :
http://ourcodeworld.com/articles/read/90/how-to-implement-fulltext-search-mysql-with-doctrine-and-symfony-3
P.S : You should be sure of what you need in your query. If you want it to be scalable, you should take a look at better search engine method as ElasticSearch or Solr.
You can inspire yourself from the following function. It iterates dynamically through all fields of the entity and depending on the type of the field a condition is applied to the query builder:
/**
* Creates the query builder used to get the results of the search query
* performed by the user in the "search" view with a given "keyword".
*
* #param array $entityConfig
* #param string $searchQuery
* #param string|null $sortField
* #param string|null $sortDirection
* #param string|null $dqlFilter
*
* #return DoctrineQueryBuilder
*/
public function createSearchQueryBuilder(array $entityConfig, $searchQuery, $sortField = null, $sortDirection = null, $dqlFilter = null)
{
/* #var EntityManager */
$em = $this->doctrine->getManagerForClass($entityConfig['class']);
/* #var DoctrineQueryBuilder */
$queryBuilder = $em->createQueryBuilder()
->select('entity')
->from($entityConfig['class'], 'entity')
;
$queryParameters = array();
foreach ($entityConfig['search']['fields'] as $name => $metadata) {
$isNumericField = in_array($metadata['dataType'], array('integer', 'number', 'smallint', 'bigint', 'decimal', 'float'));
$isTextField = in_array($metadata['dataType'], array('string', 'text', 'guid'));
if ($isNumericField && is_numeric($searchQuery)) {
$queryBuilder->orWhere(sprintf('entity.%s = :exact_query', $name));
// adding '0' turns the string into a numeric value
$queryParameters['exact_query'] = 0 + $searchQuery;
} elseif ($isTextField) {
$searchQuery = strtolower($searchQuery);
$queryBuilder->orWhere(sprintf('LOWER(entity.%s) LIKE :fuzzy_query', $name));
$queryParameters['fuzzy_query'] = '%'.$searchQuery.'%';
$queryBuilder->orWhere(sprintf('LOWER(entity.%s) IN (:words_query)', $name));
$queryParameters['words_query'] = explode(' ', $searchQuery);
}
}
if (0 !== count($queryParameters)) {
$queryBuilder->setParameters($queryParameters);
}
if (!empty($dqlFilter)) {
$queryBuilder->andWhere($dqlFilter);
}
if (null !== $sortField) {
$queryBuilder->orderBy('entity.'.$sortField, $sortDirection ?: 'DESC');
}
return $queryBuilder;
}
The source code comes from the EasyAdminBundle.

load external class and member function in Cakephp 3

I'm working on CakePHP 3.2.
I want to import data in bulk from excel file and save them to database. For this I'm using PHPExcel Library.
I have downloaded the library and extracted in vendor directory and thus the filepath to PHPExcel.php is
/vendor/PHPExcel/Classes/PHPExcel.php
and filepath to IOFactory.php is
/vendor/PHPExcel/Classes/PHPExcel/IOFactory.php
I'm including this in my controller like
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Event\Event;
include '../vendor/PHPExcel/Classes/PHPExcel.php';
include '../vendor/PHPExcel/Classes/PHPExcel/IOFactory.php';
/**
* Products Controller
*
* #property \App\Model\Table\ProductsTable $Products
*/
class ProductsController extends AppController
{
public function beforeFilter(Event $event)
{
parent::beforeFilter($event);
if ($this->Auth->user()['status'] != 1) {
$this->Auth->deny(['sell']);
}
$this->Auth->allow(['bulkUpload']);
}
public function bulkUpload()
{
$inputFileName = $this->request->data('excel_data');
if ($inputFileName != '') {
$inputFileType = PHPExcel_IOFactory::identify($inputFileName); // line 33
$objReader = PHPExcel_IOFactory::createReader($inputFileType);
$objReader->setReadDataOnly(true);
$objPHPExcel = $objReader->load($inputFileName);
$objWorksheet = $objPHPExcel->setActiveSheetIndex(0);
$highestRow = $objWorksheet->getHighestRow();
for ($row = 2; $row <= $highestRow; ++$row) {
$this->data['Program']['cycle_month'] = $objWorksheet->getCellByColumnAndRow(1, $row)->getValue();
$this->data['Program']['cycle_year'] = $objWorksheet->getCellByColumnAndRow(2, $row)->getValue();
$this->data['Program']['media_partnum'] = $objWorksheet->getCellByColumnAndRow(3, $row)->getValue();
$resultArray[$row-2] = $this->data['Program'];
}
debug($resultArray);
}
}
}
Note : I have never used such plugin and bulk upload that is why I followed code from This Question on StackOverflow
Now, the problem is, When I select a file and upload, it gives error as
Class 'App\Controller\PHPExcel_IOFactory' not found at line 33
I think the problem is with calling PHPExcel_IOFactory class.
PHPExcel_IOFactory class is inside IOFactory.php file
<?php
/** PHPExcel root directory */
if (!defined('PHPEXCEL_ROOT')) {
/**
* #ignore
*/
define('PHPEXCEL_ROOT', dirname(__FILE__) . '/../');
require(PHPEXCEL_ROOT . 'PHPExcel/Autoloader.php');
}
class PHPExcel_IOFactory
{
/**
* Search locations
*
* #var array
* #access private
* #static
*/
private static $searchLocations = array(
array( 'type' => 'IWriter', 'path' => 'PHPExcel/Writer/{0}.php', 'class' => 'PHPExcel_Writer_{0}' ),
array( 'type' => 'IReader', 'path' => 'PHPExcel/Reader/{0}.php', 'class' => 'PHPExcel_Reader_{0}' )
);
/**
* Autoresolve classes
*
* #var array
* #access private
* #static
*/
private static $autoResolveClasses = array(
'Excel2007',
'Excel5',
'Excel2003XML',
'OOCalc',
'SYLK',
'Gnumeric',
'HTML',
'CSV',
);
/**
* Private constructor for PHPExcel_IOFactory
*/
private function __construct()
{
}
public static function identify($pFilename)
{
$reader = self::createReaderForFile($pFilename);
$className = get_class($reader);
$classType = explode('_', $className);
unset($reader);
return array_pop($classType);
}
}
I see it's a simple problem of namespaces. Just put a slash before the name class as it is in the global namespace
$inputFileType = \PHPExcel_IOFactory::identify($inputFileName);
You can use composer to load PHPExcel library. It will auto include all classes in your project.
composer require phpoffice/phpexcel
Cheers :)

Resources