laravel 5.3 having error to save directory name on the fly - laravel-5.3

i have tables artists, songs, and artist_song which is the pivot table
i want song to be uploaded and stored a new directory named after the artist that belongs that song . but iam getting this error
Undefined property: Illuminate\Database\Eloquent\Relations\BelongsToMany::$name
this is my store method on SongController.
public function store(Request $request)
{
//
$this->validate($request, [
'title' => 'required',
'mp3' => 'required',
'artists' => 'required'
]);
$song = new Song;
$song->title = $request->title;
$song->lyrics = $request->lyrics;
$song->youtube_id = $request->youtube_id;
$song->album_id = $request->album_id;
$song->category_id = $request->category_id;
if($request->hasFile('mp3')){
$mp3 = $request->file('mp3');
$trackname = $mp3->getClientOriginalName();
$path = public_path('/uploads/songs/'.$song->artists()->name);
if (!file_exists($path)){
mkdir($path, 0777, true);
}
$mp3->move($path, $trackname);
$song->mp3 = $trackname;
}
$song->save();
$song->artists()->sync($request->artists, false);
return redirect()->route('song.index')->with('success', 'New song successfully upploaded');
}
i cannot get name property of that artists..
so what is wrong with my code, and one more thing to help me with is this the correct way to do relation tables like this. i referenced a tutorial about tagging and i did the same

Related

Show Content in a View if content Author has the same entity reference value as the logged in user

Title pretty much explains it. I have a user entity reference field (Node) called "Company". I want to show all content in a view where the author of that content has the same "company" value as the logged in user. I'm getting a little confused with the relationships to achieve this.
Ok, I was able to get this working based on Kien's answer. If using Entity Reference 7-x.1.5 Instead of 'field_company_nid', the correct column name was 'field_company_target_id'
/**
* Implements hook_views_query_alter().
*/
function your_module_views_query_alter(&$view, &$query) {
if ($view->name == 'article' && $view->current_display == 'page') { // replace 'article' and 'page' by your view's machine name and display's machine name
$author_join = new views_join();
$author_join->table = 'field_data_field_company'; // 'field_company' is machine name of the user's field referencing to Company
$author_join->field = 'entity_id';
$author_join->left_table = 'node';
$author_join->left_field = 'uid';
$author_join->type = 'left';
$view->query->add_relationship('author_company', $author_join, 'node');
$current_join = new views_join();
$current_join->table = 'field_data_field_company'; // 'field_company' is machine name of the user's field referencing to Company
$current_join->field = 'field_company_target_id';
$current_join->left_table = 'author_company';
$current_join->left_field = 'field_company_target_id';
$current_join->type = 'left';
$view->query->add_relationship('current_company', $current_join, 'author_company');
global $user;
$view->query->where[1]['conditions'][] = array(
'field' => 'current_company.entity_id',
'value' => $user->uid,
'operator' => '='
);
}
}
What you want seems a bit difficult to do by simply setting the view. You might need some custom code to alter the view query. Below is an approach using hook_views_query_alter():
Create a custom module (suppose it is your_module)
In file your_module.module, implement hook_views_query_alter():
/**
* Implements hook_views_query_alter().
*/
function your_module_views_query_alter(&$view, &$query) {
if ($view->name == 'article' && $view->current_display == 'page') { // replace 'article' and 'page' by your view's machine name and display's machine name
$author_join = new views_join();
$author_join->table = 'field_data_field_company'; // 'field_company' is machine name of the user's field referencing to Company
$author_join->field = 'entity_id';
$author_join->left_table = 'node';
$author_join->left_field = 'uid';
$author_join->type = 'left';
$view->query->add_relationship('author_company', $author_join, 'node');
$current_join = new views_join();
$current_join->table = 'field_data_field_company'; // 'field_company' is machine name of the user's field referencing to Company
$current_join->field = 'field_company_nid';
$current_join->left_table = 'author_company';
$current_join->left_field = 'field_company_nid';
$current_join->type = 'left';
$view->query->add_relationship('current_company', $current_join, 'author_company');
global $user;
$view->query->where[1]['conditions'][] = array(
'field' => 'current_company.entity_id',
'value' => $user->uid,
'operator' => '='
);
}
}
Enable the module you just created.

get message related to InlineKeyboardButton telegram bot after touch it

I have a command to get some suggestion/criticism in some specific categories that are shown as some InlineKeyboardButton. first user touch one of them and then should be send a simple text as suggestion/criticism.
this is my command:
class SuggestionCommand extends SystemCommand
{
protected $name = 'suggestion'; // Your command's name
protected $description = 'Suggestion Command'; // Your command description
protected $usage = '/suggestion'; // Usage of your command
protected $version = '1.0.0'; // Version of your command
public function execute()
{
$inlineKeyboard = new InlineKeyboard([]);
$inlineKeyboard->addRow(new InlineKeyboardButton([
'text' => 'Sellers',
'callback_data' => 'suggestion_sellers'
]), new InlineKeyboardButton([
'text' => 'Products',
'callback_data' => 'suggestion_products'
]));
$chat_id = $this->getMessage()->getChat()->getId();
$data = [
'chat_id' => $chat_id,
'text' => 'In which of the following areas is your suggestion / criticism: ',
'reply_markup' => $inlineKeyboard
];
return Request::sendMessage($data);
}
}
What I want to do is do that is when user enter his text I want to recognize which button is touched in The previous step because I want to do other actions based on that button.
is there any way to do that?
You need to get the callback_data value and store it in a database or JSON file. Then store the upcoming message as a reply to this value.

SQLSTATE[23000]: Integrity constraint violation in laravel5.8.35

I am very new to laravel and sqlite and am trying to create a new 'dish' to my list of dishes, however, once I submit the creation form I receive the following error:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL
constraint failed: dishes.user_id (SQL: insert into "dishes" ("name",
"price", "user_id", "updated_at", "created_at") values (Supreme Pizza,
15, ?, 2019-09-29 05:43:42, 2019-09-29 05:43:42))
I have tried a number of different modifications in my web.php, DishController, UserController, and the create.blade.php form itself, but none of the changes have worked. There were some similar questions asked here but none of the solutions helped my particular problem either.
This is my web.php file
Route::resource('dish', 'DishController');
Route::resource('user', 'UserController');
Auth::routes();
Route::get('/', 'UserController#index');
Route::get('/show/{id}', 'UserController#show');
Route::get('/show/{id}', 'UserController#create');
Route::get('users/{user}', ['as' => 'users.edit', 'uses' => 'UserController#edit']);
Route::patch('users/{user}/update', ['as' => 'users.update', 'uses' => 'UserController#update']);
Route::get('/dish', 'DishController#index');
Route::get('/show/{id}', 'DishController#show');
Route::get('/dish/create', ['as' => 'dish.create', 'uses' => 'DishController#create']);
Route::get('dishes/{dish}', ['as' => 'dish.edit', 'uses' => 'DishController#edit']);
Route::patch('dishes/{dish}/update', ['as' => 'dishes.update', 'uses' => 'DishController#update']);
Route::get('/dish/{dish}', 'DishController#destroy');
The relevant part of my DishController:
public function index()
{
$dishes = Dish::all();
return view('dishes.index')->with('dishes', $dishes);
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
return View::make('dishes.create_form')->with('users', User::all());
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255',
'price' => 'required|integer|min:1',
'user' => 'exists:user,id'
]);
$dish = new Dish();
$dish->name = $request->name;
$dish->price = $request->price;
$dish->user_id = $request->user;
$dish->save();
return redirect("dish/$dish->id");
}
And the relevant part of my create_form:
<form method="POST" action='{{url("dish")}}'>
{{csrf_field()}}
<p><label>Name: </label><input type="text" name="name" value="{{old('name')}}"></p>
<p><label>Price: </label><input type="text" name="price" value="{{old('price')}}"></p>
<p><select name="Restaurant">
#foreach ($users as $user)
#if ($user->role == 'restaurant')
<option value="{{$user->id}}" selected="selected">{{$user->name}}</option>
#endif
#endforeach
</select></p>
<input type="submit" value="Create">
</form>
The general idea is that I list my users that have a 'role' of 'restaurant'
and when I click on one, it takes me to the dishes they have (i.e. lists all dishes with selected user_id), and the option to create a new dish.
When I try to create a new dish, I input all necessary data and submit the form but I get the error message as seen in the Title. It says that dishes.user_id is null, and shows it as '?'.
This is odd since the POST data shows that:
name = "Supreme Pizza"
price = "15"
Restaurant = "7" (which is correct)
I can't for the life of me figure out what the problem is, so any help would be greatly appreciated.
In your PHP controller you are using $request->user. which i don't see in your HTML Form. So, If you want to add current user. You can use Auth.
public function store(Request $request)
{
$this->validate([
'name' => 'required|max:255',
'price' => 'required|integer|min:1',
'user' => 'exists:user,id'
]);
$dish = new Dish();
$dish->name = $request->name;
$dish->price = $request->price;
$dish->user_id = Auth::user()->id;
$dish->save();
return redirect("dish/$dish->id");
}
Please Also use Auth in top of Controller
use Auth;

Silverstripe 4 Upgrade - Unversioned DataObjects in ModelAdmin lose their image objects

Been pulling my hair out over this for a day and exhausted my google foo. I have inherited a Silverstripe 3.4 site that we have upgraded to 4.4. But something odd has been going on with certain images after running MigrateFilesTask.
I think this is something to do with a file being attached to an unversioned objects that are accessed via ModelAdmin. But I have not been able to find a definitive solution.
Code for this object below. Problems experienced are under it.
<?php
use SilverStripe\Assets\Image;
use gorriecoe\Link\Models\Link;
use SilverStripe\Security\Member;
use SilverStripe\Control\Controller;
use SilverStripe\View\Parsers\URLSegmentFilter;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\FieldGroup;
use gorriecoe\LinkField\LinkField;
use SilverStripe\TagField\TagField;
use SilverStripe\ORM\DataObject;
use SilverStripe\SelectUpload\SelectUploadField;
class Person extends DataObject
{
private static $db = array(
'FirstName' => 'Varchar(128)',
'LastName' => 'Varchar(128)',
'Role' => 'Varchar(128)',
'DirectDialNumber' => 'Varchar(128)',
'Email' => 'Varchar(128)',
'CellphoneNumber' => 'Varchar(30)',
'DirectDial' => 'Varchar(30)',
'UrlSegment' => 'Varchar(255)',
'Blurb' => 'HTMLText',
'SortOrder' => 'Int'
);
private static $has_one = array(
'Image' => Image::class,
'Office' => 'Office',
'LinkedIn' => Link::class,
'Member' => Member::class
);
private static $many_many = array(
'Interests' => 'Section'
);
private static $belongs_many_many = array(
'ElementCollection' => 'ElementCollection'
);
static $sort_fields = array(
'FirstName' => 'First name',
'LastName' => 'Last name',
'Role' => 'Role'
);
private static $summary_fields = array(
'Name' => 'Name',
'Role' => 'Role',
'Office.Name' => 'Office'
);
private static $searchable_fields = array(
'FirstName',
'LastName',
'Role'
);
// For use with the ElementCollection
public static $templates = array(
'ElementPeople' => 'Default',
'ElementPeopleAlternative' => 'Alternative'
);
public function getCMSFields() {
$fields = parent::getCMSFields();
$fields->removeByName( ['SortOrder', 'ElementCollection', 'FirstName', 'LastName', 'Interests'] );
$firstname = TextField::create('FirstName', 'First name');
$lastname = TextField::create('LastName', 'Last name');
$fields->addFieldsToTab('Root.Main', FieldGroup::create($firstname, $lastname)->setTitle('Name')->setName('Name'), 'Role');
$image = UploadField::create('Image', 'Photo');
$image->setFolderName('Uploads/People');
$image->setCanSelectFolder(false);
$fields->addFieldToTab('Root.Main', $image);
$linkedin = LinkField::create('LinkedIn', 'LinkedIn', $this);
$fields->addFieldToTab('Root.Main', $linkedin);
$interests = TagField::create(
'Interests',
'Interests Tags',
Section::get(),
$this->Interests()
)->setShouldLazyLoad(true)
->setCanCreate(false);
$fields->addFieldToTab('Root.Main', $interests);
return $fields;
}
public function onBeforeWrite()
{
$count = 1;
$this->UrlSegment = $this->generateURLSegment();
while (!$this->validURLSegment()) {
$this->UrlSegment = preg_replace('/-[0-9]+$/', null, $this->UrlSegment) . '-' . $count;
$count++;
}
parent::onBeforeWrite();
}
}
Problem #1 is after running MigrateFileTask, ALL existing images attached to instances of this class get moved from /assets/Uploads/People to /assets/.protected/Uploads/People. The confusing part here is that there is one other class called Company that is structurally near identical, yet images for that remain in /assets/Uploads/Companies as expected.
Problem #2 is if I create a new Person object and attach an image, that image is in Draft, sitting in /assets/.protected/Uploads/People with no method of actually publishing it. Meanwhile, if I do the same with a Company object, the image is still in Draft, but I can see it in the CMS.
Can someone offer some guidance on the above? At this point I'd be happy to just be able for images to be published when the DO is and I'll manually go through every single Person record and hit save myself just to get this upgrade over the line.
You should be able to fix this issue by adding the image to your DataObejct's owns property. Basically add this:
private static $owns = [
'Image'
];
Basically owns tells a DataObject which objects to publish when it is saved:
More info in the docs: https://docs.silverstripe.org/en/4/developer_guides/model/versioning/#defining-ownership-between-related-versioned-dataobjects
The cause of issue #1 was found. Leaving this here in case it helps someone in future:
The database table File has a row for every File and Folder in the system. This table has a column called "CanViewType". It exists in both Silverstripe 3 and 4.
For the particular Folder that was causing trouble during the Migration process, I found it was the only one with that column set to "OnlyTheseUsers". The rest were set to "Inherit". This was the state of the table before the upgrade.
I'm unsure how or by what mechanism that row is ever changed, but the solution to problem #1 was to manually change that field to "Inherit" before running FileMigrationTask.
Issue #2 persists, but it looks like there are two very different issues here.
OK. So sorted problem #2 finally (see other answer for solution to #1), but it's put a massive dent in our confidence in Silverstripe and sparked a meeting here.
Code for future readers:
In your unversioned DataObject, add this. In this case, my file object is called "Image". If you had more than one file to publish on save, you would have to add one of these IF blocks for each.
public function onAfterWrite()
{
if ($this->Image()->exists() && !$this->Image()->isPublished()) {
$this->Image()->doPublish();
}
parent::onAfterWrite();
}
SIDENOTE:
This Object/File relationship really is a strange design choice. Are there actually any situations where you would want to attach a file or image to a data object and NOT publish that file at the same time as you save/publish the object/page? Developers even need to explicitly define that on Versioned objects using $owns - which I'm happy to bet that most developers have to add more times than NOT. Which should really tell a us something is around wrong way.
Adding an image to a CMS system shouldn't be hard. It should take reading basic docs at the most. Not Googling, deep API doc dives (which don't answer much) or posting on StackOverlfow (where no one really knows the answer) over three days. It's an image. A core function of the product.
I've been working with SS since v2.4 and seen all the hard lessons learned to get to v4. But this appears to be a textbook case of the simple being over-engineered.

How do you Filter CSV exports on silverstripe CMS?

I am trying to export a CSV of my data which is currently displayed in a section of my Silverstripe CMS as filtered by a particular date range . It works fine at the moment when exporting the entire contents but I would like to be able to filter the results that are exported so that it returns all results within a particular date range.
My Database has a column thats records the date created - in the format 'D-M-Y; H-M-S' which I think could be used to do the filtering but I cant figure out how to set up the search filter. I understand that if you use the searchable fields and then export, you only export the filtered search results so would assume thats the best way of doing it but can't figure out how to implement it.
Any suggestions would be greatly appreciated.
-- disclaimer - I would have liked to put this on the silverstripe forum but I am completely unable to sign up for some reason - I never receive the email confirmations. ---
<?php
namespace AffiliateProgram;
use SilverStripe\Forms\GridField\GridField;
use UndefinedOffset\SortableGridField\Forms\GridFieldSortableRows;
use SilverStripe\Security\Permission;
use SilverStripe\ORM\DataObject;
class MemberBonus extends DataObject
{
private static $db = [
'Amount' => 'Currency',
'Confirmed' => 'Boolean',
'Level' => 'Int',
'Percentage' => 'Int'
];
private static $has_one = [
'Member' => 'AffiliateProgram\Member',
'MemberPayment' => 'AffiliateProgram\MemberPayment',
'PaymentType' => 'AffiliateProgram\PaymentType',
'ProgramType' => 'AffiliateProgram\ProgramType'
];
private static $summary_fields = [
'Amount' => 'Amount (USD)',
'Member.Email' => 'Email',
'Level',
'MemberPayment.PaymentType.Symbol' => 'Recieved As',
'Percentage' => 'Percentage Bonus Applied',
'ProgramType.Name' => 'Program Type',
'MemberPayment.Created' => 'Payment Date',
'Confirmed' => 'Confirmed?',
'MemberPayment.ID' => 'Payment ID'
];
}
There is also a DateCreated column on the table.
You can add custom search fields to a ModelAdmin via getSearchContext(), and customise the query based on them with getList(). See this section of the SilverStripe documentation.
Here's an example of excluding results that have a CreatedAt value below the date provided in a search field (assuming your ModelAdmin only manages MemberBonus):
<?php
use SilverStripe\Admin\ModelAdmin;
use SilverStripe\Forms\DatetimeField;
class MemberBonusAdmin extends ModelAdmin
{
...
public function getSearchContext()
{
$context = parent::getSearchContext();
$context->getFields()->push(new DatetimeField('q[CreatedAfter]', 'Created After'));
return $context;
}
public function getList()
{
$list = parent::getList();
$params = $this->getRequest()->requestVar('q');
if (!empty($params['CreatedAfter'])) {
$list = $list->exclude('CreatedAt:LessThan', $params['CreatedAfter']);
}
return $list;
}
}
To get a range working, you'd just need to add a CreatedBefore field and filter.

Resources