moodle_database::insert_record_raw() no fields found - moodle

I'm trying to extract some data from an URL and store it into a table I created in Moodle, and it shows the error in Title. My goal is to extract all the values inside the attribute "nome" on cursos>curso and put them on my table ecoclipaluno.
Example Link. parameters of build URL, when changed, can give more values to store. Or less.
https://clip.unl.pt/sprs?lg=pt&year=2013&uo=97747&srv=rsu&p=1&tp=s&md=3&rs=8145&it=5&it=1030123459
function buildURL($year, $period, $typeperiod,$course)
{
return 'https://clip.unl.pt/sprs?lg=pt&year='.$year.'&uo=97747&srv=rsu&p='.$period.'&tp='.$typeperiod.'&md=3&rs='.$course.'&it=5&it=1030123459';
}
function doRequest_with_FileGetContents($url)
{
return file_get_contents($url);
}
function processXMLforCourse($xmlContent){
$xmlObj= new SimpleXMLElement($xmlContent);
$result=array();
foreach($xmlObj->unidade_curricular->cursos->curso as $curso){
$result[]= $curso->attributes()->nome;
}
return $result;
}
$context=get_context_instance(CONTEXT_COURSE,$courseid);
//$shortname=$course->shortname;
$idnumber=$course->idnumber;
$timecreated=$course->startdate;
$typeperiod='s';
if(date("m",$timecreated) >07 && date("m",$timecreated) <13){
$period='1';
$url=buildURL(date("Y",strtotime('+1 year',$timecreated)),$period,$typeperiod,$idnumber); // 1st semester
}
else{
$period='2';
$url=buildURL(date("Y",$timecreated),$period,$typeperiod,$idnumber); // 2nd semester
}
$content_b=doRequest_with_FileGetContents($url);
$dataClipCourse= processXMLforCourse($content_b);
$DB->insert_record('ecoclipaluno',$dataClipCourse);
From the Moodle API of data manipulation, the method insert_record has 4 parameters, the last 2 being optional, but none of them specifies the field. I wanted to insert $dataClipCourse to the field coursename. How can I pull that off?
array(8) { [0]=> object(SimpleXMLElement)#37 (1) { [0]=> string(54) "Licenciatura em Engenharia Informática (Tronco comum)" } 1=> object(SimpleXMLElement)#36 (1) { [0]=> string(38) "Mestrado em Matemática e Aplicações" } 2=> object(SimpleXMLElement)#44 (1) { [0]=> string(92) "Mestrado em Matemática e Aplicações, Especialização em Álgebra, Lógica e Computação" } 3=> object(SimpleXMLElement)#45 (1) { [0]=> string(82) "Mestrado em Matemática e Aplicações, Especialização em Matemática Financeira" } [4]=> object(SimpleXMLElement)#46 (1) { [0]=> string(104) "Mestrado em Matemática e Aplicações, Especialização em Análise Numérica e Equações Diferenciais" } [5]=> object(SimpleXMLElement)#47 (1) { [0]=> string(114) "Mestrado em Matemática e Aplicações - Especialização em Atuariado, Estatística e Investigação Operacional" } [6]=> object(SimpleXMLElement)#48 (1) { [0]=> string(74) "Licenciatura em Engenharia Informática, Perfil de Ciências da Engenharia" } [7]=> object(SimpleXMLElement)#49 (1) { [0]=> string(72) "Licenciatura em Engenharia Informática, Perfil de Informática Aplicada" } }
Edit:

The second parameter for insert_record() needs be an object rather than an array and have the field names as properties. eg:
$result = new stdClass();
$result->codigo = xxx;
$result->qualificacao_atribuida = xxx;
http://docs.moodle.org/dev/Data_manipulation_API#Inserting_Records
EDIT: I just noticed the processXMLforCourse() function returns an array of names - so maybe something like this
$dataClipCourse= processXMLforCourse($content_b);
foreach ($dataClipCourse as $nome) {
$data = new stdClass();
$data->nome = $nome->__toString();
$DB->insert_record('ecoclipaluno', $data);
}

The error message means that, after removing all member variables in $dataClipCourse that didn't match a fieldname in the table 'mdl_ecoclipaluno', there was no data left to insert.
I suggest you call 'var_dump($dataClipCourse);' to see what data was being inserted, then compare this to the definition of the table 'mdl_ecoclipaluno' in your database.

Related

php8.1 - Deprecated Functionality: DateTime()

We use the following code that worked perfectly on php7.4, but we get a deprecated error on php8.1. But how can we succesfully rewrite this for php8.1?
Error:
Deprecated Functionality: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated
Current code:
$today = new \DateTime();$orderdate = new \DateTime($orders->getCreatedAt());
<?php if($orderdate->diff($today)->days > 14):?>
<?php endif;?>
You can no longer do this:
new \DateTime(null);
In your exact use case, I think that PHP has highlighted a bug in your code. If the order does not have a created at date, you'll populate the variable with the date/time when the script runs, which may not be what you want:
var_dump(new \DateTime('1985-12-31 15:00:00'));
var_dump(new \DateTime(''));
var_dump(new \DateTime(null));
object(DateTime)#1 (3) {
["date"]=>
string(26) "1985-12-31 15:00:00.000000"
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "Europe/Amsterdam"
}
object(DateTime)#1 (3) {
["date"]=>
string(26) "2022-09-19 12:28:23.003960"
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "Europe/Amsterdam"
}
Deprecated: DateTime::__construct(): Passing null to parameter #1 ($datetime) of type string is deprecated in /in/67OFM on line 5
object(DateTime)#1 (3) {
["date"]=>
string(26) "2022-09-19 12:28:23.003987"
["timezone_type"]=>
int(3)
["timezone"]=>
string(16) "Europe/Amsterdam"
}
Demo
If you want to use DB information:
$orderdate = $orders->getCreatedAt()
? new \DateTime($orders->getCreatedAt())
: null;
If you want to default to "now", make it explicit so nobody wonders whether it's intentional:
$orderdate = $orders->getCreatedAt()
? new \DateTime($orders->getCreatedAt())
: new \DateTime();
Last but not least... Analyse if it makes sense from the business logic standpoint to have orders with no creation date. What does that mean?

Unexpected data found during update on eloquent / Laravel

I am using ajax to update a model that contains timestamps, but it throw me an exception:
{message: "Unexpected data found.", exception: "InvalidArgumentException",…}
message: "Unexpected data found."
exception: "InvalidArgumentException"
file: "/home/asus/Devagnos/almada/vendor/nesbot/carbon/src/Carbon/Traits/Creator.php"
line: 623
trace: [,…]
i have disabled the timestamps and i set the dateformat like this:
protected $dateFormat = 'Y-m-d H:i:s.u';
public $timestamps = false;
protected $dates = [
'created_at',
'updated_at'
];
alse I added these methods
/**
* #param $val
*/
public function setCreatedAtAttribute($val)
{
return Carbon::createFromFormat('Y-m-d H:i:s.u', $val);
}
/**
* #param $val
*/
public function setUpdatedAtAttribute($val)
{
return Carbon::createFromFormat('Y-m-d H:i:s.u', $val);
}
but I am always getting the same error, What am I doing wrong ?
I'm using laravel 6.8 and postgresql
If you're trying to use microseconds, then you should refer to this guide from the documentation:
https://carbon.nesbot.com/laravel/
I don't get what you tried with setCreatedAtAttribute and setUpdatedAtAttribute, setters are supposed to change the inner property, not to return a value.
Then check you gave to your DB columns enough precision (such as TIMESTAMP(6)) in your migration schemas.

How natural sorting a varchar column with Doctrine

I have a table with a column that contains names (varchar) but some names have numbers inside and the ordering is not the expected.
I have something like:
Courlis
D11 Espadon
D13 Balbuzard
D1 empacher
D2
But I expect:
Courlis
D1 empacher
D2
D11 Espadon
D13 Balbuzard
I've found lot of tips about it, but it's always on ordering numbers only stored as string: add a 0 to convert it in numbers, check the length of the string to place 1 before 10, etc... But in my case it can't work.
I can't use SQL query, because I use it in a form of a Symfony application that need a QueryBuilder.
Here is a way to do this with ICU collations in PostgreSQL (available from v10 on):
CREATE COLLATION en_natural (
LOCALE = 'en-US-u-kn-true',
PROVIDER = 'icu'
);
CREATE TABLE atable (textcol text COLLATE en_natural);
COPY atable FROM STDIN;
Enter data to be copied followed by a newline.
End with a backslash and a period on a line by itself, or an EOF signal.
>> Courlis
>> D11 Espadon
>> D13 Balbuzard
>> D1 empacher
>> D2
>> \.
test=# SELECT textcol FROM atable ORDER BY textcol;
textcol
---------------
Courlis
D1 empacher
D2
D11 Espadon
D13 Balbuzard
(5 rows)
Thanks to Laurentz Albe for your answer,for a Step by step in a Symfony application:
Create a Migration file that create the custom collation
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20200221215657 extends AbstractMigration
{
public function getDescription() : string
{
return '';
}
public function up(Schema $schema) : void
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('CREATE COLLATION fr_natural (provider = "icu", locale = "fr-u-kn-true");');
}
public function down(Schema $schema) : void
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.');
$this->addSql('DROP COLLATION fr_natural');
}
}
Create a Doctrine Custom Function (Collate DQL)
<?php
namespace App\DQL;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
class Collate extends FunctionNode
{
public $expressionToCollate = null;
public $collation = null;
public function parse(\Doctrine\ORM\Query\Parser $parser)
{
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->expressionToCollate = $parser->StringPrimary();
$parser->match(Lexer::T_COMMA);
$parser->match(Lexer::T_IDENTIFIER);
$lexer = $parser->getLexer();
$this->collation = $lexer->token['value'];
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(\Doctrine\ORM\Query\SqlWalker $sqlWalker)
{
return sprintf( '%s COLLATE %s', $sqlWalker->walkStringPrimary($this->expressionToCollate), $this->collation );
}
}
Register the new Function in the Doctrine config
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
server_version: '12'
orm:
auto_generate_proxy_classes: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
dql:
string_functions:
collate: App\DQL\Collate
And finally juste use it in the query when needed
$query = $this->createQueryBuilder('shell')
->orderBy('COLLATE(shell.name, fr_natural)', 'ASC')
->getQuery();
return $query->getResult();

Error when trying to insert input from user into SQL table

I'm having a problem, whenever I try to run the code below and select the statement 2 to insert a tool and put a random tool name I get the error message : ProgrammingError('column "inserttool' does not exist\nLine 1: insert tools(tool_name, rental_days) values(#insertTool, '2') .
Here is the code :
if Menu == "2":
cursor = connection.cursor()
InsertTool = raw_input("Please insert the tool that you want to add.\n")
insert_tool = """insert into tools(tool_name, rental_days) values(#InsertTool, '2')"""
try:
cursor.execute( insert_tool);
connection.commit();
print("Tool is succesfully inserted!")
except Exception as e:
connection.rollback();
print("Exception Occured : ",e)
connection.close();
try this.
if Menu == "2":
cursor = connection.cursor()
InsertTool = raw_input("Please insert the tool that you want to add.\n")
insert_tool = """insert into tools(tool_name, rental_days) values(%s, %s)"""
val = (InsertTool, "2")
try:
cursor.execute(insert_tool, val);
connection.commit();
print("Tool is succesfully inserted!")
except Exception as e:
connection.rollback();
print("Exception Occured : ",e)
connection.close();

I need to know how to disable the CSRF function in Impresspages cms

I need to know how to disable the CSRF function in Impresspages cms. i saw a possible answer provided on a previous thread, but wasnt fully sorted. When my customer logs into my impress pages site at: cleanwaterpartnership.co.uk, he gets an "ERROR undefined" message. In the log files on the cms system it states:
Core.possibleCsrfAttack.
The notes say:
array(1) {
["post"]=>
array(6) {
["securityToken"]=> string(32) "b2766e9f8578bf04d456952a35882bb4"
["antispam"]=> array(2) { [0]=> string(0) "" [1]=> string(32) "ea3810b9e1da7fdaffe4003836be0541" }
["sa"]=> string(15) "Admin.loginAjax"
["global_error"]=> string(0) ""
["login"]=> string(16) "Alastair Stewart"
["password"]=> string(16) "XXXXXXXXX" }
}
Use PublicController type. https://www.impresspages.org/docs/controller
This type of controller doesn't do any checks.