Yii2 - foreach loop to save all files path in database model - file

Greetings,
i'm using a multiple file upload input in Yii2.
The multiole file input is saving very well the files selected inside a folder called audio.
The problen is i cannot inside foreach loop save the name and path of each file in the database model Faixas.php inside a field called ficheiro.
Here is my code:
Controller:
public function actionCreate()
{
$model = new Faixas();
if (Yii::$app->request->isPost) {
$model->files = UploadedFile::getInstances($model, 'files');
if ($model->upload()) {
return $this->render('create', ['model' => $model]);
}
}
return $this->render('create', ['model' => $model]);
}
The Model as a function named upload() to save the files in folder, but the part to save inside the model->ficheiro is not working (don't figure it out ?):
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
$model = new Faixas();
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
And finally the view, which renders the input:
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'files[]')->fileInput(['multiple' => true, 'accept' => 'audio/*']) ?>
<button>Submit</button>
Any ideas on the way to get it done?
Many thanks...
The entire Faixas.php model class:
<?php
namespace app\models;
use Yii;
/**
* This is the model class for table "faixas".
*
* #property integer $id
* #property string $nome
* #property string $ficheiro
* #property string $dummy1
* #property string $dummy2
* #property string $dummy3
* #property string $dummy4
* #property string $dummy5
*/
class Faixas extends \yii\db\ActiveRecord
{
/**
* #inheritdoc
*/
public static function tableName()
{
return 'faixas';
}
public $files;
/**
* #inheritdoc
*/
public function rules()
{
return [
[['nome', 'ficheiro', 'dummy1', 'dummy2', 'dummy3', 'dummy4', 'dummy5'], 'string', 'max' => 255],
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
];
}
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
// this part in not working, why ????
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}
/**
* #inheritdoc
*/
public function attributeLabels()
{
return [
'id' => Yii::t('app', 'ID'),
'nome' => Yii::t('app', 'Nome'),
'ficheiro' => Yii::t('app', 'Ficheiro'),
'dummy1' => Yii::t('app', 'Dummy1'),
'dummy2' => Yii::t('app', 'Dummy2'),
'dummy3' => Yii::t('app', 'Dummy3'),
'dummy4' => Yii::t('app', 'Dummy4'),
'dummy5' => Yii::t('app', 'Dummy5'),
];
}
// coloca o Audio na GridView
public function getAudio()
{
return \Yii::$app->request->BaseUrl.'/'.$this->ficheiro;
}
}

Seems you create the model in wrog place. You create a $model = new Faixas(); ouuside the loop. try creating inside.
public function upload()
{
if ($this->validate()) {
foreach ($this->files as $file) {
$file->saveAs('audio/' . $file->baseName . '.' . $file->extension);
$model = new Faixas();
$filePath = 'audio/' . $file->baseName . '.' . $file->extension;
$model->ficheiro = $filePath;
$model->save();
}
return true;
} else {
return false;
}
}

SOLVED... removed from the model file the rule:
[['files'], 'file', 'skipOnEmpty' => false, 'extensions' => 'mp3, ogg, webm', 'maxFiles' => 30],
Now the foreach() loop saves every file Path in the database.
Many thanks to all that somehow tried to achieve a solution.

Related

PHPstan: Cannot access property $work on array|EntityInterface|null

I am developing a web app, trying to keep PHPstan's suggestions in check.
I am having some difficulties with this method:
/**
* AJAX: deletes a work file
*
* #return \Cake\Http\Response|false
*/
public function delete()
{
$this->autoRender = false;
$this->viewBuilder()->setLayout('ajax');
$this->request->allowMethod(['post', 'delete']);
$data = $this->request->getData();
$data = is_array($data) ? $data : [$data];
$workFile = $this->WorkFiles->find('all')
->where(['WorkFiles.id' => $data['id']])
->contain(['Works'])
->first();
$res = [
'status' => 'error',
'message' => __('The file could not be deleted. Please, try again.'),
'class' => 'alert-error',
];
if ($workFile->work->anagraphic_id == $this->authAnagraphics['id']) { // error #1
if ($this->WorkFiles->delete($workFile)) { // error #2
$res = [
'status' => 'success',
'message' => __('File successfully deleted.'),
'class' => 'alert-success',
];
}
}
return $this->response->withStringBody((string)json_encode($res));
}
The code itself works, but I'm having two phpstan errors:
[phpstan] Cannot access property $work on array|Cake\Datasource\EntityInterface|null.
[phpstan] Parameter #1 $entity of method Cake\ORM\Table::delete() expects Cake\Datasource\EntityInterface, array|Cake\Datasource\EntityInterface|null given.
Am I doing something wrong?
Always use inline annotation then here:
/** #var \App\Model\Entity\WorkFile|null $workFile */
$workFile = $this->WorkFiles->find('all')
->where(['WorkFiles.id' => $data['id']])
->contain(['Works'])
->first();
But the comments are right, you are blindly using a possible null value afterwards, as such your code is not written correctly.
Use this instead:
/** #var \App\Model\Entity\WorkFile $workFile */
$workFile = $this->WorkFiles->find('all')
->where(['WorkFiles.id' => $data['id']])
->contain(['Works'])
->firstOrFail();

Cannot instantiate abstract class Cake\Mailer\Mailer

I want to build forgot password page in cakephp
Here is my code of user controller
<?php
namespace App\Controller;
use App\Controller\AppController;
use Cake\Http\Exception\UnauthorizedException;
use Cake\Mailer\Email;
use Cake\Mailer\Mailer;
use Cake\email\TransportFactory;
use Cake\Auth\DefaultPasswordHasher;
use Cake\Utility\Security;
use Cake\ORM\TableRegistry;
use Cake\Core\InstanceConfigTrait;
/**
Users Controller
#property \App\Model\Table\UsersTable $Users
#method \App\Model\Entity\User[]|\Cake\Datasource\ResultSetInterface paginate($object = null, array $settings = [])
*/
class UsersController extends AppController {
public function beforeFilter(\Cake\Event\Event $event) {
$this->Auth->allow([‘add’, ‘logout’]);
parent::beforeFilter($event);
}
/**
Index method
#return \Cake\Http\Response|null
*/
public function index() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException(__(‘You are not allowed to access this page’));
}
$users = $this->paginate($this->Users);
$this->set(compact(‘users’));
}
/**
View method
#param string|null $id User id.
#return \Cake\Http\Response|null
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function view($id = null) {
$user = $this->Users->get($id, [
‘contain’ => [],
]);
$this->set(‘user’, $user);
}
/**
Add method
#return \Cake\Http\Response|null Redirects on successful add, renders view otherwise.
*/
public function add() {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->newEntity();
if ($this->request->is(‘post’)) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Edit method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects on successful edit, renders view otherwise.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function edit($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$user = $this->Users->get($id, [
‘contain’ => [],
]);
if ($this->request->is([‘patch’, ‘post’, ‘put’])) {
$user = $this->Users->patchEntity($user, $this->request->getData());
if ($this->Users->save($user)) {
$this->Flash->success((‘The user has been saved.’));
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('The user could not be saved. Please, try again.'));
}
$this->set(compact(‘user’));
}
/**
Delete method
#param string|null $id User id.
#return \Cake\Http\Response|null Redirects to index.
#throws \Cake\Datasource\Exception\RecordNotFoundException When record not found.
*/
public function delete($id = null) {
if ($this->Auth->user(‘role’) != ‘admin’) {
throw new UnauthorizedException((‘You are not allowed to access this page’));
}
$this->request->allowMethod([‘post’, ‘delete’]);
$user = $this->Users->get($id);
if ($this->Users->delete($user)) {
$this->Flash->success((‘The user has been deleted.’));
} else {
$this->Flash->error(__(‘The user could not be deleted. Please, try again.’));
}
return $this->redirect([‘action’ => ‘index’]);
}
public function forgotpassword()
{
if ($this->request->is(‘post’)) {
$email = $this->request->getData(‘email’);
$token = Security::hash(Security::randomBytes(25));
$userTable = TableRegistry::get(‘Users’);
if ($email == NULL) {
$this->Flash->error((‘Please insert your email address’));
}
if ($user = $userTable->find(‘all’)->where([‘email’=>$email])->first()) {
$user->token = $token;
if ($userTable->save($user)){
$mailer = new Mailer(‘default’);
$mailer->Transport(‘Smtp’);
$mailer->From([‘noreply[at]codethepixel.com’ => ‘myCake4’])
->setTo($email)
->setEmailFormat(‘html’)
->setSubject(‘Forgot Password Request’)
->deliver(‘Hello
Please click link below to reset your password
Reset Password’);
}
$this->Flash->success(‘Reset password link has been sent to your email (’.$email.’), please check your email’);
}
if ($total = $userTable->find(‘all’)->where([‘email’=>$email])->count()==0) {
$this->Flash->error((‘Email is not registered in system’));
}
}
}
public function resetpassword($token)
{
if($this->request->is(‘post’)){
$hasher = new DefaultPasswordHasher();
$newPass = $hasher->hash($this->request->getData(‘password’));
$userTable = TableRegistry::get(‘Users’);
$user = $userTable->find(‘all’)->where([‘token’=>$token])->first();
$user->password = $newPass;
if ($userTable->save($user)) {
$this->Flash->success(‘Password successfully reset. Please login using your new password’);
return $this->redirect([‘action’=>‘login’]);
}
}
}
public function login() {
if ($this->request->is(‘post’)) {
$user = $this->Auth->identify();
if ($user) {
if ($user[‘is_active’] === 1) {
$users = $this->Users->get($user[‘id’]);
$users->ip_address = $this->request->clientIp();
$users->last_login = date(‘Y-m-d h:i:s’);
if ($this->Users->save($users)) {
$this->Auth->setUser($user);
return $this->redirect($this->Auth->redirectUrl());
} else {
$this->Flash->error((‘Unable to login by your credentials.’));
}
} else {
$this->Flash->error((‘This user not activated, please contact our administrator.’));
}
}
$this->Flash->error(__(‘Invalid username or password, try again’));
}
}
public function logout() {
return $this->redirect($this->Auth->logout());
}
}
After opening forgot password page user enter their email following error received.
Cannot instantiate abstract class Cake\Mailer\Mailer
How do I solve this problem when the user entered their email & reset password will be sent to user's email which will be saved in our database.
Help me please #ndm
In your app.php
use Cake\Mailer\Transport\MailTransport;
.
.
.
'EmailTransport' => [
'default' => [
'className' => MailTransport::class,
/*
* The following keys are used in SMTP transports:
*/
'host' => 'localhost',
'port' => 25,
'timeout' => 30,
'username' => null,
'password' => null,
'client' => null,
'tls' => null,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
'your_project' => [
'className' => 'Smtp',
'host' => 'your_host',
'port' => XXX,
'timeout' => 30,
'username' => 'your_email',
'password' => 'your_password',
'client' => null,
'tls' => true,
'url' => env('EMAIL_TRANSPORT_DEFAULT_URL', null),
],
],
'Email' => [
'default' => [
'transport' => 'default',
'from' => 'you#localhost',
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
'your_project' => [
'transport' => 'your_project',
'from' => ['your_email#teste.com' => 'My Site'],
//'charset' => 'utf-8',
//'headerCharset' => 'utf-8',
],
],
Create a folder "Mailer" in src/Mailer. Create an UserMailer.php file
<?php
namespace App\Mailer;
use Cake\Mailer\Mailer;
class UserMailer extends Mailer
{
public static $name = 'User';
public function reset($user)
{
$this->to($user->email)
->profile('your_project')
->emailFormat('html')
->template('your_project', 'user')
->layout('user')
->viewVars(['name' => $user->name])
->subject(sprintf('Welcome...', $user->name))
->message("texte...");
}
}
In this case, I created a layout for my email. Create an "Email" folder in the layout.
On your controller, do the following:
$this->getMailer('User')->send('reset', [$user]);
Don't forget to import into the controller:
use Cake\Mailer\MailerAwareTrait;
I use it like this.
Go to the godaddy dashboard and find the SMTP information. It's all you need! Replace with your information

write data to db in yii2

I have signup form which register a new user. But when i input data all fields exept one(username) saving in DB. I can't figure why. Help me.
here is my code from SignupForm
<?php
namespace app\modules\user\models;
use yii\base\Model;
use Yii;
/**
* Signup form
*/
class SignupForm extends Model
{
public $username;
public $email;
public $password;
public $verifyCode;
public function rules()
{
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['username', 'match', 'pattern' => '#^[\w_-]+$#i'],
['username', 'unique', 'targetClass' => User::className(), 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'unique', 'targetClass' => User::className(), 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
['verifyCode', 'captcha', 'captchaAction' => '/user/default/captcha'],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'username' => Yii::t('app', 'USER_USERNAME'),
'email' => Yii::t('app', 'USER_EMAIL'),
'password' => Yii::t('app', 'USER_PASSWORD'),
'verifyCode' => Yii::t('app', 'USER_VERIFYCODE'),
];
}
/**
* Signs user up.
*
* #return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->status = User::STATUS_WAIT;
$user->generateAuthKey();
$user->generateEmailConfirmToken();
if ($user->save()) {
Yii::$app->mailer->compose('#app/modules/user/mails/emailConfirm', ['user' => $user])
->setFrom([Yii::$app->params['supportEmail'] => Yii::$app->name])
->setTo($this->email)
->setSubject('Email confirmation for ' . Yii::$app->name)
->send();
}
return $user;
}
return null;
}
}
code from signup(view)
<?php
use yii\captcha\Captcha;
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
/* #var $this yii\web\View */
/* #var $form yii\bootstrap\ActiveForm */
/* #var $model app\modules\user\models\SignupForm */
$this->title = Yii::t('app', 'TITLE_SIGNUP');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="user-default-signup">
<h1><?= Yii::t('app', 'TITLE_SIGNUP') ?></h1>
<p>Please fill out the following fields to signup:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
<?= $form->field($model, 'username') -> textInput() ?>
<?= $form->field($model, 'email') -> textInput() ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'captchaAction' => '/user/default/captcha',
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>
code from DefaultController
...
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
Yii::$app->getSession()->setFlash('success', 'Подтвердите ваш электронный адрес.');
return $this->goHome();
}
}
return $this->render('signup', [
'model' => $model,
]);
}
...
code from User(model)
<?php
namespace app\modules\user\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\helpers\ArrayHelper;
use yii\web\IdentityInterface;
/**
* This is the model class for table "{{%user}}".
*
* #property integer $id
* #property integer $created_at
* #property integer $updated_at
* #property string $username
* #property string $auth_key
* #property string $email_confirm_token
* #property string $password_hash
* #property string $password_reset_token
* #property string $email
* #property integer $status
*/
class User extends ActiveRecord implements IdentityInterface
{
const SCENARIO_PROFILE = 'profile';
const STATUS_BLOCKED = 0;
const STATUS_ACTIVE = 1;
const STATUS_WAIT = 2;
public $id;
public $username;
public $password;
public $authKey;
public $accessToken;
public function rules()
{
return [
['username', 'required'],
['username', 'match', 'pattern' => '#^[\w_-]+$#i'],
['username', 'unique', 'targetClass' => self::className(), 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'required', 'except' => self::SCENARIO_PROFILE],
['email', 'email', 'except' => self::SCENARIO_PROFILE],
['email', 'unique', 'targetClass' => self::className(), 'except' => self::SCENARIO_PROFILE, 'message' => Yii::t('app', 'ERROR_EMAIL_EXISTS')],
['email', 'string', 'max' => 255, 'except' => self::SCENARIO_PROFILE],
['status', 'integer'],
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => array_keys(self::getStatusesArray())],
];
}
public function attributeLabels()
{
return [
'id' => 'ID',
'created_at' => Yii::t('app', 'USER_CREATED'), //'Создан',
'updated_at' => Yii::t('app', 'USER_UPDATE'), //'Обновлён',
'username' => Yii::t('app', 'USER_USERNAME'), // 'Имя пользователя',
'email' => Yii::t('app', 'USER_EMAIL'), // 'Email',
'status' => Yii::t('app', 'USER_STATUS'), //'Статус',
];
}
public function scenarios()
{
return [
self::SCENARIO_DEFAULT => ['username', 'email', 'status'],
self::SCENARIO_PROFILE => ['email'],
];
}
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* #inheritdoc
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* #inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('findIdentityByAccessToken is not implemented.');
}
/**
* Finds user by username
*
* #param string $username
* #return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username]);
}
/**
* #inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* #inheritdoc
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* #inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* #param string $password password to validate
* #return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
public function getStatusName()
{
return ArrayHelper::getValue(self::getStatusesArray(), $this->status);
}
public static function getStatusesArray()
{
return [
self::STATUS_BLOCKED => 'Заблокирован',
self::STATUS_ACTIVE => 'Активен',
self::STATUS_WAIT => 'Ожидает подтверждения',
];
}
/**
* #param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
public function beforeSave($insert)
{
if (parent::beforeSave($insert)) {
if ($insert) {
$this->generateAuthKey();
}
return true;
}
return false;
}
//************************************
/**
* Finds user by password reset token
*
* #param string $token password reset token
* #return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds out if password reset token is valid
*
* #param string $token password reset token
* #return boolean
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
$parts = explode('_', $token);
$timestamp = (int) end($parts);
return $timestamp + $expire >= time();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
//************************************
/**
* #param string $email_confirm_token
* #return static|null
*/
public static function findByEmailConfirmToken($email_confirm_token)
{
return static::findOne(['email_confirm_token' => $email_confirm_token, 'status' => self::STATUS_WAIT]);
}
/**
* Generates email confirmation token
*/
public function generateEmailConfirmToken()
{
$this->email_confirm_token = Yii::$app->security->generateRandomString();
}
/**
* Removes email confirmation token
*/
public function removeEmailConfirmToken()
{
$this->email_confirm_token = null;
}
}
It's because you have got username attribute directly declared in User model here:
public $username;
Remove it so it can be mapped by ActiveRecord.
See the note in the guide about this.

How to upload file using Cakephp 3.0?

I am trying to create a file upload on cakephp, I haven't been able to find any decent tutorials for cakephp 3.0 that go in detail, and I don't understand how to install plugins.
I have this in my add section
echo $this->Form->create('filename', array('action' => 'upload', 'type' => 'file'));
echo $this->Form->file('filename');
I haven't added anything in the controller yet
/**
* Index method
*
* #return void
*/
public function index()
{
$this->paginate = [
'contain' => ['Courses']
];
$this->set('contents', $this->paginate($this->Contents));
$this->set('_serialize', ['contents']);
}
/**
* View method
*
* #param string|null $id Content id.
* #return void
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function view($id = null)
{
$content = $this->Contents->get($id, [
'contain' => ['Courses']
]);
$this->set('content', $content);
$this->set('_serialize', ['content']);
}
/**
* Add method
*
* #return void Redirects on successful add, renders view otherwise.
*/
public function add()
{
$content = $this->Contents->newEntity();
if ($this->request->is('post')) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Edit method
*
* #param string|null $id Content id.
* #return void Redirects on successful edit, renders view otherwise.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function edit($id = null)
{
$content = $this->Contents->get($id, [
'contain' => []
]);
if ($this->request->is(['patch', 'post', 'put'])) {
$content = $this->Contents->patchEntity($content, $this->request->data);
if ($this->Contents->save($content)) {
$this->Flash->success('The content has been saved.');
return $this->redirect(['action' => 'index']);
} else {
$this->Flash->error('The content could not be saved. Please, try again.');
}
}
$courses = $this->Contents->Courses->find('list', ['limit' => 200]);
$this->set(compact('content', 'courses'));
$this->set('_serialize', ['content']);
}
/**
* Delete method
*
* #param string|null $id Content id.
* #return void Redirects to index.
* #throws \Cake\Network\Exception\NotFoundException When record not found.
*/
public function delete($id = null)
{
$this->request->allowMethod(['post', 'delete']);
$content = $this->Contents->get($id);
if ($this->Contents->delete($content)) {
$this->Flash->success('The content has been deleted.');
} else {
$this->Flash->error('The content could not be deleted. Please, try again.');
}
return $this->redirect(['action' => 'index']);
}
but after this no idea what to do.
First of all, you need to decide on WHEN you're going to handle uploads. I've managed to create a dirty (but working) approach using beforeMarshal method and afterSave method (I'll explain why these two at the end).
If you create your file input like:
<?= $this->Form->file('submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
or for hasMany association:
<?= $this->Form->file('images.'.$i.'.submittedfile', ['class' => 'form-control input-upload', 'style' => 'height:100px']) ?>
and you define the right associations:
$this->hasMany('Images', [
'foreignKey' => 'model_id'
]);
you could process those files before the Entity gets patched and saved:
public function beforeMarshal(Event $event, \ArrayObject $data, \ArrayObject $options) {
$images = array();
$dir = md5(time().$data['name']);
for ($i = 0; $i < count($data['images']); $i++) {
$image = $data['images'][$i]['submittedfile'];
if (!empty($image['name'])) {
if(!isset($data['id'])) {
$data['temp_dir'] = $dir;
}
else {
$dir = $data['id'];
}
if ($this->Images->uploadFile(array('img', 'model', $dir), $image) === true) {
$images[] = array('name' => pathinfo($image['name'], PATHINFO_FILENAME), 'ext' => pathinfo($image['name'], PATHINFO_EXTENSION));
}
}
}
$data['images'] = $images;
}
This is of course an example. I've decided to check, if there's an ID property set on the Entity (like for edit), because if it's not (like for create), you have to somehow identify the right path.
Here you've got a file uploading function:
public function uploadDir($path = array()) {
return $this->wwwRoot . implode(DS, $path);
}
public function uploadFile($path = array(), $filetoupload = null) {
if (!$filetoupload) {
return false;
}
$dir = new Folder($this->uploadDir($path), true, 755);
$tmp_file = new File($filetoupload['tmp_name']);
if (!$tmp_file->exists()) {
return false;
}
$file = new File($dir->path . DS . $filetoupload['name']);
if (!$tmp_file->copy($dir->pwd() . DS . $filetoupload['name'])) {
return false;
}
$file->close();
$tmp_file->delete();
return true;
}
If you added your images while there was no subdirectory with main entity ID, you have to rename the directory as soon as you get the ID:
public function afterSave(Event $event, Entity $entity, \ArrayObject $options) {
if(!empty($entity->temp_dir)) {
$this->Images->renameFolder(array('img', 'model', $entity->temp_dir),$entity->id);
}
}
calling:
public function renameFolder($path = array(), $newName) {
$oldPath = $this->wwwRoot . implode(DS, $path);
$nameToChange = array_pop($path);
array_push($path, $newName);
$newPath = $this->wwwRoot . implode(DS, $path);
return rename($oldPath, $newPath);
}
Using beforeMarshal you're able to inject your file data into Entity structure before the whole Entity is ready for saving (with associations).
Using afterSave you're able to identify the main object ID and call the set of objects you've uploaded before.
Remember to set recursive rights for saving files onto the directory, as well as rights for creating and renaming directories.

Tried to use TinyMce in cakephp but it is not working

I tried to use the TinyMce plugin in cakephp but the editor is not loading but the helpers are. Even after extracting the files to the plugins folder and adding the codes in bootstrap.php file its not working.
Helper:
<?php
App::uses('AppHelper', 'View/Helper');
class TinymceHelper extends AppHelper {
// Take advantage of other helpers
public $helpers = array('Js', 'Html', 'Form');
// Check if the tiny_mce.js file has been added or not
public $_script = false;
/**
* Adds the tiny_mce.js file and constructs the options
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname"
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #return string JavaScript code to initialise the TinyMCE area
*/
function _build($fieldName, $tinyoptions = array()){
if(!$this->_script){
// We don't want to add this every time, it's only needed once
$this->_script = true;
$this->Html->script('tiny_mce/tiny_mce', array('inline' => false));
}
// Ties the options to the field
$tinyoptions['mode'] = 'exact';
$tinyoptions['elements'] = $this->domId($fieldName);
// List the keys having a function
$value_arr = array();
$replace_keys = array();
foreach($tinyoptions as $key => &$value){
// Checks if the value starts with 'function ('
if(strpos($value, 'function(') === 0){
$value_arr[] = $value;
$value = '%' . $key . '%';
$replace_keys[] = '"' . $value . '"';
}
}
// Encode the array in json
$json = $this->Js->object($tinyoptions);
// Replace the functions
$json = str_replace($replace_keys, $value_arr, $json);
$this->Html->scriptStart(array('inline' => false));
echo 'tinyMCE.init(' . $json . ');';
$this->Html->scriptEnd();
}
/**
* Creates a TinyMCE textarea.
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname"
* #param array $options Array of HTML attributes.
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #param string $preset
* #return string An HTML textarea element with TinyMCE
*/
function textarea($fieldName, $options = array(), $tinyoptions = array(), $preset = null){
// If a preset is defined
if(!empty($preset)){
$preset_options = $this->preset($preset);
// If $preset_options && $tinyoptions are an array
if(is_array($preset_options) && is_array($tinyoptions)){
$tinyoptions = array_merge($preset_options, $tinyoptions);
}else{
$tinyoptions = $preset_options;
}
}
return $this->Form->textarea($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}
/**
* Creates a TinyMCE textarea.
*
* #param string $fieldName Name of a field, like this "Modelname.fieldname"
* #param array $options Array of HTML attributes.
* #param array $tinyoptions Array of TinyMCE attributes for this textarea
* #return string An HTML textarea element with TinyMCE
*/
function input($fieldName, $options = array(), $tinyoptions = array(), $preset = null){
// If a preset is defined
if(!empty($preset)){
$preset_options = $this->preset($preset);
// If $preset_options && $tinyoptions are an array
if(is_array($preset_options) && is_array($tinyoptions)){
$tinyoptions = array_merge($preset_options, $tinyoptions);
}else{
$tinyoptions = $preset_options;
}
}
$options['type'] = 'textarea';
return $this->Form->input($fieldName, $options) . $this->_build($fieldName, $tinyoptions);
}
/**
* Creates a preset for TinyOptions
*
* #param string $name
* #return array
*/
private function preset($name){
// Full Feature
if($name == 'full'){
return array(
'theme' => 'advanced',
'plugins' => 'safari,pagebreak,style,layer,table,save,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,media,searchreplace,print,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,template',
'theme_advanced_buttons1' => 'save,newdocument,|,bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull,styleselect,formatselect,fontselect,fontsizeselect',
'theme_advanced_buttons2' => 'cut,copy,paste,pastetext,pasteword,|,search,replace,|,bullist,numlist,|,outdent,indent,blockquote,|,undo,redo,|,link,unlink,anchor,image,cleanup,help,code,|,insertdate,inserttime,preview,|,forecolor,backcolor',
'theme_advanced_buttons3' => 'tablecontrols,|,hr,removeformat,visualaid,|,sub,sup,|,charmap,emotions,iespell,media,advhr,|,print,|,ltr,rtl,|,fullscreen',
'theme_advanced_buttons4' => 'insertlayer,moveforward,movebackward,absolute,|,styleprops,|,cite,abbr,acronym,del,ins,attribs,|,visualchars,nonbreaking,template,pagebreak',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_statusbar_location' => 'bottom',
'theme_advanced_resizing' => true,
'theme_advanced_resize_horizontal' => false,
'convert_fonts_to_spans' => true,
'file_browser_callback' => 'ckfinder_for_tiny_mce'
);
}
// Basic
if($name == 'basic'){
return array(
'theme' => 'advanced',
'plugins' => 'safari,advlink,paste',
'theme_advanced_buttons1' => 'code,|,copy,pastetext,|,bold,italic,underline,|,link,unlink,|,bullist,numlist',
'theme_advanced_buttons2' => '',
'theme_advanced_buttons3' => '',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'center',
'theme_advanced_statusbar_location' => 'none',
'theme_advanced_resizing' => false,
'theme_advanced_resize_horizontal' => false,
'convert_fonts_to_spans' => false
);
}
// Simple
if($name == 'simple'){
return array(
'theme' => 'simple',
);
}
// BBCode
if($name == 'bbcode'){
return array(
'theme' => 'advanced',
'plugins' => 'bbcode',
'theme_advanced_buttons1' => 'bold,italic,underline,undo,redo,link,unlink,image,forecolor,styleselect,removeformat,cleanup,code',
'theme_advanced_buttons2' => '',
'theme_advanced_buttons3' => '',
'theme_advanced_toolbar_location' => 'top',
'theme_advanced_toolbar_align' => 'left',
'theme_advanced_styles' => 'Code=codeStyle;Quote=quoteStyle',
'theme_advanced_statusbar_location' => 'bottom',
'theme_advanced_resizing' => true,
'theme_advanced_resize_horizontal' => false,
'entity_encoding' => 'raw',
'add_unload_trigger' => false,
'remove_linebreaks' => false,
'inline_styles' => false
);
}
return null;
}
}
I used the following codes in my view file:
<?php
echo $this->Html->script('/TinyMCE/js/tiny_mce/tiny_mce.js', array(
'inline' => false)); ?>
<script type="text/javascript">
tinyMCE.init({
theme : "advanced",
mode : "textareas",
convert_urls : false,
theme_advanced_buttons1 : "bold,italic,underline,blockquote,separator,strikethrough,justifyleft,justifycenter,justifyright, justifyfull,bullist,numlist,undo,redo,link,unlink",
theme_advanced_buttons2: "",
theme_advanced_buttons3: "",
theme_advanced_buttons4: "",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left"
});
</script>
I added this code in my controller:
public $helpers = array('Tinymce');
I have solved it... I just inserted it manually and the problem was in setting the path to the js file.

Resources