solarium show error with laravel 6 ( & solr 6) - ubuntu-18.04

Getting following error after upgrading laravel 5.8 to 6.2 ( using ubuntu 18 , PHP 7.3.28) & its working properly in laravel 5.8.
Declaration of Symfony\Component\EventDispatcher\EventDispatcher::dispatch($event) must be compatible with Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch(object $event, ?string $eventName = NULL): object
namespace App\Http\Services;
use Solarium\Client;
use Solarium\Core\Client\Adapter\Curl;
use Symfony\Component\EventDispatcher\EventDispatcher;
class RoiSolr {
public function __construct() {
$adapter = new Curl();
**$dispatcher = new EventDispatcher();**
$options = config('solarium');
$this->client = new Client($adapter, $dispatcher, $options);
}
*
*
*
*
<other functions>
}
?>```
Thanks in advance.

Related

Mock databases function from drupal 7

I want to create a phpunit test from the following code, but I'm not even sure if it worth it, because the code contains db_update and db_query functions, so, those are database functions and I don't know if it make sense create a test for this, because I don't know if should assume drupal code is working fine.
<?php
namespace Drupal\forum_innovation\Forum;
/**
* Created by PhpStorm.
* User: ldcontreras
* Date: 30/05/18
* Time: 18:26
*/
class ForumCounter implements ForumInterface {
public static function setForumCounter($forum, $uid) {
$counterState = db_update('forum_counter_states')
->fields(array(
'state' => 'read',
))
->condition('uid', $uid)
->condition('tid', $forum)
->execute();
return $counterState;
}
public static function getForumNotification($forum, $uid) {
$unReadNotifications =
db_query('SELECT count(*) as counter
FROM {forum_counter_states} as f WHERE f.uid = :uid AND f.state = :state AND f.tid = :forum',
array(
':uid' => $uid,
':forum' => $forum,
':state' => 'unread'
)
)->fetchAll();
return $unReadNotifications[0]->counter;
}
}
I'm trying to create a test like this, but I need some help and clarification:
<?php
/**
* Created by PhpStorm.
* User: ldcontreras
* Date: 8/06/18
* Time: 10:02
*/
namespace Drupal\forum_innovation\Forum;
class ForumCounterTest extends \PHPUnit_Framework_TestCase {
public function TestSetForumCounter() {
$db_query = $this->getMock('db_update', array('fields', 'condition', 'execute'));
$db_query->expects($this->once())->method('fields')->with($this->equalTo(array(':uid' => 3024));
$db_query->expects($this->once())->method('condition')->with($this->equalTo(array(':uid' => 3024)));
$db_query->expects($this->once())->method('condition')->with($this->equalTo(
array(':tid' => 83))->will(
$this->returnCallback('callback'));
}
}
Thanks!

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.

Typo3 cal (calendar Base) use event objects in foreign extension

I'm working on an extension that's depending on cal base. I fetch events from other sources by crawling their websites.
I'm slowly converting to extbase and I'd like to know if or how it is possible to access cal base events from my extension.
I know that I could just access the tables using mapOnProperty. But then I would have to rewrite the whole logic, too.
I wonder if it's possible to just use the objects of calendar base.
I tried to write a test:
<?php
class CalEventTest extends \TYPO3\CMS\Core\Tests\BaseTestCase {
/**
* #test
*/
public function anInstanceOfCalEventCanBeConstructed() {
$calEventService = & \TYPO3\CMS\Cal\Utility\Functions::getEventService ();
// $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
// $calEventService = $objectManager->get('TYPO3\CMS\Cal\Service\EventService');
// $calEventService = new TYPO3\CMS\Cal\Service\EventService();
// $events = $calEventService->findAll(array(1));
}
}
You see different attempts commented out. They all failed in one or the other way. CalEventService looked promising but it also doesn't work. The error for the last approach is.
Call to a member function isLoggedIn() on null in /var/www/clients/client4/web47/web/typo3conf/ext/cal/Classes/Service/NearbyEventService.php on line 27
I wonder if this approach is possible at all before trying some more (the mentioned error seems connected to the test environment context).
I'm using Typo3 6.2.27 and cal 1.10.1.
Not jet tested, but as the Manual says you should access the EventService like this:
$storagePageID = 123;
/** #var \TYPO3\CMS\Cal\Service\EventService $eventService **/
$eventService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceService('tx_cal_phpicalendar', 'cal_event_model');
$events = $eventService->findAll($storagePageID);
I found the cal API which looks promising
/**
* #test
*/
public function calApiCanBeAccessed() {
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$calAPIPre = $objectManager->get('TYPO3\CMS\Cal\Controller\Api');
$this->assertInstanceOf(TYPO3\CMS\Cal\Controller\Api::class, $calAPIPre);
$this->assertObjectHasAttribute('prefixId', $calAPIPre);
$pidList = "1095, 80";
$calAPI = $calAPIPre->tx_cal_api_without($pidList);
$this->assertInstanceOf(TYPO3\CMS\Cal\Controller\Api::class, $calAPI);
$this->assertObjectHasAttribute('prefixId', $calAPI);
$this->assertInstanceOf(TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::class, $calAPI->cObj);
}
and successfully returns an event object
/**
* #test
*/
public function calEventCanBeFoundThroughApi() {
$pidList = "1095, 80";
$eventUid = '2670';
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$calAPI = $objectManager->get('TYPO3\CMS\Cal\Controller\Api')->tx_cal_api_without($pidList);
$event = $calAPI->findEvent($eventUid, 'tx_cal_phpicalendar', $pidList);
$this->assertInstanceOf(TYPO3\CMS\Cal\Model\Eventmodel::class, $event);
}
internally it seems to use the approach of simulating a TSFE context (if no cObj is present, I didn't try the tx_cal_api_with(&$cObj, &$conf) method using an existing cObj).
Having read an old thread from 2012 (https://forum.typo3.org/index.php/t/192263/) I implemented that in my Typo3 6.2 setting:
<?php
class CalEventTest extends \TYPO3\CMS\Core\Tests\BaseTestCase {
/**
* #test
*/
public function anInstanceOfCalEventCanBeConstructed() {
$rightsObj = &\TYPO3\CMS\Cal\Utility\Registry::Registry ('basic', 'rightscontroller');
$rightsObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceService('cal_rights_model', 'rights');
$rightsObj->setDefaultSaveToPage();
$modelObj = &\TYPO3\CMS\Cal\Utility\Registry::Registry('basic','modelcontroller');
$modelObj = new \TYPO3\CMS\Cal\Controller\ModelController();
$viewObj = &\TYPO3\CMS\Cal\Utility\Registry::Registry('basic','viewcontroller');
$viewObj = new \TYPO3\CMS\Cal\Controller\ViewController();
$objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\CMS\Extbase\Object\ObjectManager');
$configurationManager = $objectManager->get('TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface');
$controller = &\TYPO3\CMS\Cal\Utility\Registry::Registry('basic','controller');
$controller = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Cal\\Controller\\Controller');
$cObj = &\TYPO3\CMS\Cal\Utility\Registry::Registry('basic','cobj');
$cObj = $configurationManager->getContentObject();
$cObj = new TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer();
$GLOBALS['TSFE'] = new \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController($GLOBALS['TYPO3_CONF_VARS'], $pid, '0', 1, '', '', '', '');
$GLOBALS['TSFE']->cObj = $cObj;
$GLOBALS['TSFE']->sys_page = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\Page\\PageRepository');
$storagePageID = "1095, 80";
$eventService = & \TYPO3\CMS\Cal\Utility\Functions::getEventService ();
if ($eventService) {
$events = $eventService->findAll($storagePageID);
\TYPO3\CMS\Core\Utility\GeneralUtility::devLog('2', $this->getDebugId()."-".__FUNCTION__, -1, array($events, $eventService->getServiceKey ()) );
}
}
}
This works but it I find it extremely ugly. I'll try the cal api next.
(this has been an edit to my question but it's actually an answer)

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 :)

CakePHP 2.0 - Use MySQL ENUM field with form helper to create Select Input

I've been researching a bit and I found that CakePHP's form helper doesn't interpret ENUM fields correctly, so it simply outputs a text input. I found a post that suggested to use a helper for that specific purpose. Does anybody know a better way to achieve this? Or if CakePHP devs intend to correct this some day?
Thanks for reading!
Below is one of the helper extention.
App::uses('FormHelper', 'View/Helper');
/**
* APP/View/Helper/MySqlEnumFormHelper.php
* It extends FormHelper to implement ENUM datatype of MySQL.
*
* http://blog.xao.jp/blog/cakephp/implementation-of-mysql-enum-datatype-in-formhelper/
*
* created Oct. 15, 2012
* CakePHP 2.2.3
*/
class MySqlEnumFormHelper extends FormHelper
{
public function input($fieldName, $options = array())
{
if (!isset($options['type']) && !isset($options['options'])) {
$modelKey = $this->model();
if (preg_match(
'/^enum\((.+)\)$/ui',
$this->fieldset[$modelKey]['fields'][$fieldName]['type'],
$m
)) {
$match = trim($m[1]);
$qOpen = substr($match, 0, 1);
$qClose = substr($match, -1);
$delimiter = $qOpen . ',' . $qClose;
preg_match('/^'.$qOpen.'(.+)'.$qClose.'$/u', $match, $m);
$_options = explode($delimiter, $m[1]);
$options['type'] = 'select';
$options['options'] = array_combine($_options, $_options);
}
}
return parent::input($fieldName, $options);
}
}
Cake attempts to be database agnostic and therefore this issue won't be "corrected" since it's not a bug. For example, SQL server doesn't have an exact equivalent of MySQL's ENUM field type.
I would recommend getting your possible list of enum values like so:
YourController.php
// get column type
$type = $this->Model->getColumnType('field');
// extract values in single quotes separated by comma
preg_match_all("/'(.*?)'/", $type, $enums);
// enums
var_dump($enums[1]);
Then use a select field in your view and pass the enums as options. Your current value you'll already have. How does that sound?
I am new to cakephp I found some old code and pieced together an enum select box for you enjoy
/**
* Behavior with useful functionality around models containing an enum type field
*
* Copyright (c) Debuggable, http://debuggable.com
*
*
*
* #package default
* #access public
*
* reworked by Nathanael Mallow for cakephp 2.0
*
*/
/*
*Use case:Add this (EnumerableBehavior.php) to app/Model/Behavior/
* -->in the Model add public $actsAs = array('Enumerable');
* -->in the *_controller add $enumOptions = $this->Categorie->enumOptions('Section');
* -->in the view add print $this->Form->input('{db_field_name}', array('options' => $enumOptions, 'label' => 'here'));
*
*
*/
class EnumerableBehavior extends ModelBehavior {
/**
* Fetches the enum type options for a specific field
*
* #param string $field
* #return void
* #access public
*/
function enumOptions($model, $field) {
//Cache::clear();
$cacheKey = $model->alias . '_' . $field . '_enum_options';
$options = Cache::read($cacheKey);
if (!$options) {
$sql = "SHOW COLUMNS FROM `{$model->useTable}` LIKE '{$field}'";
$enumData = $model->query($sql);
$options = false;
if (!empty($enumData)) {
$enumData = preg_replace("/(enum|set)\('(.+?)'\)/", '\\2', $enumData[0]['COLUMNS']['Type']);
$options = explode("','", $enumData);
}
Cache::write($cacheKey, $options);
}
return $options;
}
}
?>
If you want to use MySqlEnumFormHelper instead of normal and call it by $this->Form-> instead by $this->MySqlEnumFormHelper . You should add this line in your controller to alias MySqlEnumFormHelper as Form.
public $helpers = array('Form' => array(
'className' => 'MySqlEnumForm'
));
/* comments about previus answers ***
Use case:Add this (EnumerableBehavior.php) to app/Model/Behavior/
-->in the Model add public $actsAs = array('Enumerable');
-->in the action of the *_controller add $enumOptions = $this->YourModelName->enumOptions('db_field_name'); $this->set('enumOptions',$enumOptions);
-->in the view add print $this->Form->input('{db_field_name}', array('options' => $enumOptions, 'label' => 'here'));
*
*/
i think the Behaviour way it's good...but the array keys are integer
so i have modified the function like this
function enumOptions($model, $field) {
//Cache::clear();
$cacheKey = $model->alias . '_' . $field . '_enum_options';
$options = Cache::read($cacheKey);
$enumOptions = array();
if (!$options) {
$sql = "SHOW COLUMNS FROM `{$model->useTable}` LIKE '{$field}'";
$enumData = $model->query($sql);
$options = false;
if (!empty($enumData)) {
$enumData = preg_replace("/(enum|set)\('(.+?)'\)/", '\\2', $enumData[0]['COLUMNS']['Type']);
$options = explode("','", $enumData);
foreach ($options as $option) {
$enumOptions["$option"] = $option;
}
}
Cache::write($cacheKey, $enumOptions);
}
return $enumOptions;
}
in order to be able to save the right value in the db field when the form is submitted
I created a function that goes into AppController to handle this. I combined some of the information provided above.
Usage:
$enumList = getEnumValues($ModelField) where ModelField is in this format: 'Model.Field'
Function that I put in AppController:
function getEnumValues($ModelField){
// split input into Model and Fieldname
$m = explode('.', $ModelField);
if ($m[0] == $ModelField) {
return false;
} else {
(! ClassRegistry::isKeySet($m[0])) ? $this->loadModel($m[0]): false;
$type = $this->$m[0]->getColumnType($m[1]);
preg_match_all("/'(.*?)'/", $type, $enums);
foreach ($enums[1] as $value){$enumList[$value] = $value;}
return $enumList;
}
}

Resources