I created a custom module where in the block I display the weather using data from https://openweathermap.org/
Code of this block:
https://phpsandbox.io/n/sweet-forest-1lew-1wmof
Also I have WeatherForm.php file with the form which adds in a configuration city and an API key for which it is necessary to display weather.
I needed to Add form validation:
fields should not be empty
City name should not contain numbers
I did it this way:
public function validateForm(array &$form, FormStateInterface $form_state) {
$pattern = '/[0-9]/';
if (empty($form_state->getValue('weather_city'))) {
$form_state->setErrorByName('weather_city', $this->t('Fields should not be empty'));
}
if (preg_match($pattern, $form_state->getValue('weather_city'))) {
$form_state->setErrorByName('weather_city', $this->t('City name should not contain numbers'));
}
}
But I got these remark after the code review:
Also, will be good to validate the API key and the city name by the API request.
I found an example of how to implement this:
public function validateWeatherData(string $city_name, $api_key):bool {
try {
$url = "https://api.openweather.org/data/2.5/weather?q=$city_name&appid=$api_key";
$response = $this->client->request('GET', $url);
if ($response->getStatusCode() != 200) {
throw new \Exception('Failed to retrieve data.');
}
$reg_ex = "#^[A-Za-z-]=$#";
return preg_match($reg_ex, $city_name);
}
catch (GuzzleException $e) {
return FALSE;
}
}
But I don't know how to integrate the example code into my function validateForm. What my code should look like so that it also implements validate the API key and the city name by the API request?
All code of my Form:
https://phpsandbox.io/n/spring-mountain-gdnn-emozx
Why not use both, brainstorm with me something along the lines of..
function validateWeatherData($city, $apikey) {
try {
$url = "https://api.openweather.org/data/2.5/weather?q=$city_name&appid=$api_key"; // Build the URL
$response = file_get_contents($url); // You can use cURL here as well incase CORS blocks file_get_contents
return $response; // Return the data from the call made above
}
catch (Exception $e) {
return $e;
}
}
function validateForm(array &$form, FormStateInterface $form_state) {
$pattern = '/[0-9]/';
if (empty($form_state->getValue('weather_city'))) {
$form_state->setErrorByName('weather_city', $this->t('Fields should not be empty'));
return false; // Failed to validate city, return false go back start again
}
if (preg_match($pattern, $form_state->getValue('weather_city'))) {
$form_state->setErrorByName('weather_city', $this->t('City name should not contain numbers'));
return false; // Failed to validate city, return false go back start again
}
$apikey = "ABCDEFG"; // API key (can be conditional based on city via CASE/IF when needed)
$weatherdata = validateWeatherData($form_state->getValue('weather_city'), $apikey); // Validate weather data
return $weatherdata; // Return validateWeatherData's response or do something else with it
}
Related
In gutenberg/block-editor, how can I check whether I've already registered a block type? Is there a function I can use? Searching through the Block Editor Handbook I couldn't see a function to check this.
An example of what I am trying to do is below:
class My_Block {
public function __construct() {
if ( ! SOME_FUNCTION_block_exists('foo/column') ) {
register_block_type( 'foo/column', my_args );
}
}
}
In WordPress Gutenberg, using JavaScript you can check if a block exists by name with getBlockType(), eg:
JavaScript
import { getBlockType } from '#wordpress/blocks';
import { registerBlockType } from '#wordpress/blocks';
if (!getBlockType('foo/column')) {
registerBlockType('foo/column', {
edit: Edit,
save,
});
}
While the above is probably the prefered way, there is a valid case for checking in PHP if a block is already registered, eg. if you want to add a render callback for a block with server side rendering. While I haven't seen a core function for this, I've found a way it can be done by using the REST API endpoint for block-types to search for the block by namespace/name:
PHP
class My_Block
{
public function __construct()
{
if (! is_block_registered('foo/column')) {
register_block_type('foo/column', $args);
}
}
private function is_block_registered($block_name)
{
// Use REST API to query if block exists by <namespace>/<name>
$route = new WP_REST_Request('GET', '/wp/v2/block-types/' . $block_name);
$request = rest_do_request($route);
if ($request->status == 404) {
// Block is not found/registered
return false;
}
// Block is registered (status is 200)
return true;
}
}
There is the method ´is_registered()´ in the class ´WP_Block_Type_Registry´ (that class handles the registration of blocks). See the docs: https://developer.wordpress.org/reference/classes/wp_block_type_registry/is_registered/
class My_Block {
public function __construct() {
if ( ! WP_Block_Type_Registry::get_instance()->is_registered( 'foo/column' ) ) {
register_block_type( 'foo/column', my_args );
}
}
}
public function followers()
{
return $this->belongsToMany('App\User', 'follower_following', 'following_id', 'follower_id')
->select('id', 'uname', 'name');
}
public function following()
{
return $this->belongsToMany('App\User', 'follower_following', 'follower_id', 'following_id')
->select('id', 'uname', 'name');
}
public function files(){
return $this->hasMany(Files::class)
->orderBy('created_at');
}
how to i fetch files of user followig
i have tried this method
$file = Files::whereIn('user_id',$followers)
->with('user')
->latest()
->limit(10)
->get();
but it shows undefined $followers
If I understood it well, you want to fetch files of user's followers.
Have you tried something like this:
App\User::with('followers.files')->find(1);
I would like to add a select field in admin/post-new.php.
This select field will be populated with JSON data (from a GET URL).
^ This point is solved. In your function.php:
function acf_load_colors_field_choices($field) {
$field['choices'] = [];
$choices = json_decode(file_get_contents('http://127.0.0.1/json/colors'), true);
if (is_array($choices)) {
foreach ($choices as $choice) {
$field['choices'][$choice] = $choice;
}
}
return $field;
}
add_filter('acf/load_field/name=colors', 'acf_load_colors_field_choices');
Once the page is ready to be published, I would like to catch POST data to send them to another URL.
How to catch those data?
In functions.php, to catch POST data:
function on_save_post_articles($post_id) {
var_dump($post_id);
var_dump($_POST);
exit;
}
add_action('save_post', 'on_save_post_articles');
Solved!
I have a view form that contains a table with textfield inside it.
I need to save the information of the table inside a database.
* javascript function *
function sendTableToServer()
{
var table;
table = document.getElementById('myTable');
var rowLength = table.rows.length;
var tableArray = [rowLength -1];
var JSONObject;
for (var tblRow = 1; tblRow < rowLength; tblRow++){
console.log("***** ROW CHANGE *****");
JSONObject = {
"rowIndex": "myTableRow" + tblRow,
"partNo": table.rows[tblRow].cells[0].firstChild.value,
"partName":table.rows[tblRow].cells[1].firstChild.value,
};
f24Array[tblRow] = JSONObject;
}
console.log(f24Array[rowLength-1]["rowIndex"]);
console.log(f24Array.length -1);
$.getJSON("f24BatcCreateEAF.do", {
type: "F24",
pRefForm: "DVL",
pF24Values: tableArray
}
, function(ans) {
console.log("The row is" +ans.strVar);
}
);
};
* controller *
public #ResponseBody
AjaxReturnMessage createEaf( Model model, HttpServletRequest pRequest, #RequestParam String type, #RequestBody String[] pF24Values ) throws Exception {
long eafId=0;
AjaxReturnMessage pARM = new AjaxReturnMessage();
log.info( "entering creatEaf );
try {
System.out.println("calling gF24BatchService");
eafId = gF24BatchService.createEAFRow( model, pp, type, pRefForm, pDescription );
pARM.setId( eafId );
pARM.setStrVar( "f24TableRow1" );
pARM.setCode( AjaxReturnMessage.STATUS_ERROR );
} catch ( Exception e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// return the jsp page only
return pARM;
}
When i trigger the sendTableToServer function i get an error "404".
But if i remove the pF24Values from the JSON call and he service then there is no error.
How would it be possible for me to "catch" pF24Values without having to create a new object type. is this possible?
Thanks
You are performing a GET to your controller, so that controller can only capture data via request parameters. In addition, your getJSON function is sending all the data as request parameters as well.
Therefore your controller has to capture pF24Values as a #RequestParam, not as a #RequestBody.
If you want to send complex data structures to your controller you need to do a POST with the JSON as the request body (for instance) - although you can use GET for array data but not the way you are doing it here - each row needs to have a separate request param(e.g. pF24Values:one and pF24Values:two, etc - there are a few ways to do this).
I build a model side validation in Laravel 4 with the creating Model Event :
class User extends Eloquent {
public function isValid()
{
return Validator::make($this->toArray(), array('name' => 'required'))->passes();
}
public static function boot()
{
parent::boot();
static::creating(function($user)
{
echo "Hello";
if (!$user->isValid()) return false;
});
}
}
It works well but I have issues with PHPUnit. The two following tests are exactly the same but juste the first one pass :
class UserTest extends TestCase {
public function testSaveUserWithoutName()
{
$count = User::all()->count();
$user = new User;
$saving = $user->save();
assertFalse($saving); // pass
assertEquals($count, User::all()->count()); // pass
}
public function testSaveUserWithoutNameBis()
{
$count = User::all()->count();
$user = new User;
$saving = $user->save();
assertFalse($saving); // fail
assertEquals($count, User::all()->count()); // fail, the user is created
}
}
If I try to create a user twice in the same test, it works, but it's like if the binding event is present only in the first test of my test class. The echo "Hello"; is printed only one time, during the first test execution.
I simplify the case for my question but you can see the problem : I can't test several validation rules in different unit tests. I try almost everything since hours but I'm near to jump out the windows now ! Any idea ?
The issue is well documented in Github. See comments above that explains it further.
I've modified one of the 'solutions' in Github to automatically reset all model events during the tests. Add the following to your TestCase.php file.
app/tests/TestCase.php
public function setUp()
{
parent::setUp();
$this->resetEvents();
}
private function resetEvents()
{
// Get all models in the Model directory
$pathToModels = '/app/models'; // <- Change this to your model directory
$files = File::files($pathToModels);
// Remove the directory name and the .php from the filename
$files = str_replace($pathToModels.'/', '', $files);
$files = str_replace('.php', '', $files);
// Remove "BaseModel" as we dont want to boot that moodel
if(($key = array_search('BaseModel', $files)) !== false) {
unset($files[$key]);
}
// Reset each model event listeners.
foreach ($files as $model) {
// Flush any existing listeners.
call_user_func(array($model, 'flushEventListeners'));
// Reregister them.
call_user_func(array($model, 'boot'));
}
}
I have my models in subdirectories so I edited #TheShiftExchange code a bit
//Get all models in the Model directory
$pathToModels = '/path/to/app/models';
$files = File::allFiles($pathToModels);
foreach ($files as $file) {
$fileName = $file->getFileName();
if (!ends_with($fileName, 'Search.php') && !starts_with($fileName, 'Base')) {
$model = str_replace('.php', '', $fileName);
// Flush any existing listeners.
call_user_func(array($model, 'flushEventListeners'));
// Re-register them.
call_user_func(array($model, 'boot'));
}
}