how to fetch files of user following by user - laravel-5.7

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

Related

Validate the API key and the city name by the API request

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
}

Checking permission in Sonata Admin lists

I need to disable downloading lists and also customize the query depending on user permission in Sonata Admin
This limits the list results based on Role
public function createQuery($context = 'list')
{
$query = parent::createQuery($context);
$security_context = $this->getConfigurationPool()->getContainer()->get('security.context');
$user = $security_context->getToken()->getUser();
$staff = $this->getConfigurationPool()->getContainer()->get('doctrine')->getRepository('AppBundle:Staff')->findOneBy(array('user' => $user));
if ($security_context->isGranted('ROLE_ADMIN') && !$security_context->isGranted('ROLE_EXECUTIVE_ADMIN'))
{
$query->andWhere($query->getRootAlias().'.store',':store');
$query->setParameter('store', $staff->getStore());
}
return $query;
}
This should hide the download button based on permission
protected function configureRoutes(RouteCollection $collection)
{
$collection->remove('delete')
->remove('create');
$security_context = $this->getConfigurationPool()->getContainer()->get('security.context');
if ($security_context->isGranted('ROLE_ADMIN') && !$security_context->isGranted('ROLE_EXECUTIVE_ADMIN'))
{
$collection->remove('export');
}
}
How can I achieve the intended obijectives because this implementation returns the error below:
The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL in . (which is being imported from "E:\www\project\app/config\routing.yml").
After Symfony 2.6 security.context is deprecatedm now you should use security.authorization_checker service: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements
Now its like this:
protected function configureRoutes(RouteCollection $collection)
{
$collection->remove('delete')
->remove('create');
$authorization_checker = $this->getConfigurationPool()->getContainer()->get('authorization_checker');
if ($authorization_checker->isGranted('ROLE_ADMIN') && !$authorization_checker->isGranted('ROLE_EXECUTIVE_ADMIN'))
{
$collection->remove('export');
}
}

Permissions for ModelAdmin DataObjects

When a user is not an Admin, but his assigned group has access to a ModelAdmin the model admin page is listed in the menu & the user can visit it, however no records show in the index view.
To show the records, the permissions need to be set in the model. The documentation says to do it like this:
http://doc.silverstripe.org/framework/en/3.1/reference/modeladmin
class Category extends DataObject {
// ...
public function canView($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canEdit($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canDelete($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
public function canCreate($member = null) {
return Permission::check('CMS_ACCESS_CMSMain', 'any', $member);
}
}
However this does not work as $member is Null. Setting these methods to return true displays the records. Is this secure? Or does that set anybody to be able to edit the records? logging in as a user whose group does not have access to that model admin seems to not allow them to get to the listing page, but it seems like the wrong thing to do.
public function canView($member = null) {
return null;
}
public function canEdit($member = null) {
return true;
}
public function canDelete($member = null) {
return true;
}
public function canCreate($member = null) {
return true;
}
What is the best way to allow a group to view & edit a modelAdmin's records?
The example is what you want to follow, though with a different permission name. The permission name in the example is if the user has access to CMSMain, which is the part go the CMS that handles pages.
To get the name of the permission, you take the class name of your ModelAdmin (say, CategoryAdmin) and prepend CMS_ACCESS_ to it (which would give CMS_ACCESS_CategoryAdmin in this example).
As for $member being null, that is only the default value. So $member is only null if no value is passed in. This doesn't actually matter though, as Permission::check specifically handles being passed in a null value and uses the current logged in user instead.

Laravel 4 Model Events don't work with PHPUnit

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'));
}
}

Symfony2 set class variable with init or construct methods

Have recently been using Symfony2 after using ZF for some time.
I am having problems trying to do something relatively simple, I think.
The following code is within a controller:
private $current_setid = "";
public function __construct() {
$current_set = $this->getCurrentSet();
if ($current_set == "") {
return $this->redirect($this->generateUrl('selectset'));
}
$this->current_setid = $current_set;
}
public function getCurrentSet() {
$session = $this->get("session");
$set = $session->get('set');
return $set;
}
public function setCurrentSet($setid) {
$session = $this->get("session");
$session->set('set', "$setid");
}
If I use __construct() I get errors like:
Fatal error: Call to a member function get() on a non-object in
I have tried using __init() and init() both of which do not seem to get called.
Can anyone point me in the right direction? Is there a simple way to do this or do I have to look into event listeners?
Have you tried getting your session like they do in official documentation?
$session = $this->getRequest()->getSession();
$foo = $session->get('foo');
Basically get fetch dependencies from container and container in the Controller is injected using setter dependency injection. You just not have container in the time of __construct yet.
Just ended up opting for placing a check in every method in the class. Seems silly to have to do that but I find I often have to do that in Symfony2 with the lack of init, postDispatch type methods like ZF has.
Even trying to remove the check to another method was counter productive as I still had to check the return from that method as $this->redirect does not seem to work unless it is within an Action method. For example:
public function isSetSet() {
$current_set = $this->getCurrentSet();
if ($current_set == "") {
$url = $this->generateUrl('selectset');
return $this->redirect($url);
}
return TRUE;
}
public function someAction() {
$check = $this->isSetSet();
if($check != TRUE){
return $check;
}
...
}
So each method needs that 4 line check but the whole check can be done in 4 lines anyway so no need for that extra method:
public function anotherAction() {
$current_setid = $this->getCurrentSet();
if ($current_setid == "") {
return $this->redirect($this->generateUrl('selectset'));
}
...
}

Resources