I have following model and controller. And database table pages has id, title, content and slug.
Q1. Why does the line in controller,
$this->load->model("pagemodel", 'pages'); // Load the page model,
have 'pages'?
Is it naming "pagemodel" as pages?
And I see a line,
$page_data = $this->pages->fetch($page_slug); // Pull the page data from the database
using pages.
Model code
<?php
class Pagemodel extends Model
{
/**
* Constructor
*/
function Pagemodel()
{
parent::Model();
}
/**
* Return an array of pages — used in the manage view
*
* #access public
* #return array
*/
function pages()
{
$query = $this->db->query("SELECT * FROM `pages` ORDER BY `id` ASC");
return $query->result_array();
}
/**
* Return a list of a single page — used when editing a page
*
* #access public
* #param integer
* #return array
*/
function page($id)
{
$query = $this->db->query("SELECT * FROM `pages` WHERE `id` = '$id' LIMIT 1");
return $query->result_array();
}
/**
* Return an array of a page — used in the front end
*
* #access public
* #param string
* #return array
*/
function fetch($slug)
{
$query = $this->db->query("SELECT * FROM `pages` WHERE `slug` = '$slug'");
return $query->result_array();
}
/**
* Add a record to the database
*
* #access public
* #param array
*/
function add($data)
{
$this->db->query("INSERT INTO `pages` (`title`, `content`, `slug`) VALUES (".$this->db->$data['title'].", ".$this->db->$data['content'].", ".$this->db->escape($data['slug']).")");
}
/**
* Update a record in the database
*
* #access public
* #param integer
* #param array
*/
function edit($id, $data)
{
$this->db->query("UPDATE `pages` SET `title` = ".$this->db->escape($data['title']).", `content` = ".$this->db->escape($data['content']).", `slug` = ".$this->db->escape($data['slug'])." WHERE `id` = '$id'");
}
/**
* Remove a record from the database
*
* #access public
* #param integer
*/
function delete($id)
{
$this->db->query("DELETE FROM `pages` WHERE `id` = '$id'");
}
}
?>
Controller code
<?php
class Page extends Application
{
function Page()
{
parent::Application();
$this->load->model("pagemodel", 'pages'); // Load the page model
}
function _view($page, $page_data)
{
$meta = array (
'meta_title' => 'title here',
'meta_keywords' => 'keywords here',
'meta_description' => 'description here',
'meta_robots' => 'all',
'extra_headers' => '
<script language="javascript" type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.0/jquery.min.js"></script>
'
);
$data = array();
// add any data
// merge meta and data
$data = array_merge($data,$meta);
// load view with data
$this->load->view('header', $data);
$this->load->view($page, $page_data);
$this->load->view('footer');
}
function index()
{
$page_slug = $this->uri->segment('2'); // Grab the URI segment
if($page_slug === FALSE)
{
$page_slug = 'home'; //Change home if you change the name in the back-end
}
$page_data = $this->pages->fetch($page_slug); // Pull the page data from the database
if($page_data === FALSE)
{
show_404(); // Show a 404 if no page exists
}
else
{
$this->_view('index', $page_data[0]);
}
}
}
?>
From system/libraries/Loader.php
/**
* Model Loader
*
* This function lets users load and instantiate models.
*
* #access public
* #param string the name of the class
* #param string name for the model
* #param bool database connection
* #return void
*/
function model($model, $name = '', $db_conn = FALSE)
{
...
So yes, the second parameter is just setting a 'friendly' name for the model, and is not needed. It adds a layer of confusion in my opinion.
You are probably right, try renaming 'pages' and I bet it's not available anymore by calling
$this->pages in your controller code.
Related
I already had a question regarding "importing" records and there data of different plugins/extensions. I got it working after adding the pid and implemented a query builder to get the data of a different plugin (or table in this case). But now I got the problem that the images of the "foreign" table/records or whatever is not included.. when I debug the var the image is only set to int 1. But they are not correctly included. What do I need to do to get this s*** working? :)
//MY CONTROLLER
<?php
namespace Formschoen\Mitarbeiterajax\Controller;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Utility\GeneralUtility;
/**
* MitarbeiterController
*/
class MitarbeiterController extends \TYPO3\CMS\Extbase\Mvc\Controller\ActionController
{
/**
* mitarbeiterRepository
*
* #var \Formschoen\Mitarbeiterajax\Domain\Repository\MitarbeiterRepository
*/
protected $mitarbeiterRepository = null;
/**
* #param \Formschoen\Mitarbeiterajax\Domain\Repository\MitarbeiterRepository $mitarbeiterRepository
*/
public function injectMitarbeiterRepository(\Formschoen\Mitarbeiterajax\Domain\Repository\MitarbeiterRepository $mitarbeiterRepository)
{
$this->mitarbeiterRepository = $mitarbeiterRepository;
}
/**
* optionRecordRepository
*
* #var \Sebkln\Ajaxselectlist\Domain\Repository\OptionRecordRepository
*/
protected $optionRecordRepository;
/**
* #param \Sebkln\Ajaxselectlist\Domain\Repository\OptionRecordRepository
*/
public function injectOptionRecordRepository(\Sebkln\Ajaxselectlist\Domain\Repository\OptionRecordRepository $optionRecordRepository) {
$this->optionRecordRepository = $optionRecordRepository;
}
/**
* action list
*
* #return void
*/
public function listAction()
{
$mitarbeiters = $this->mitarbeiterRepository->findAll();
$this->view->assign('mitarbeiters', $mitarbeiters);
$this->view->assign("currentPageID", $GLOBALS['TSFE']->id);
$options['autohaus'] = array(
1 => 'some strings'
);
$options['abteilung'] = array(
1 => 'some strings'
);
$this->view->assign('options', $options);
}
/**
* action callAjax
*
* #param \Formschoen\Mitarbeiterajax\Domain\Model\Mitarbeiter $mitarbeiter
* #return void
*/
public function callAjaxAction(\Formschoen\Mitarbeiterajax\Domain\Model\Mitarbeiter $mitarbeiter)
{
$optionRecords = $this->optionRecordRepository->findAll();
$arguments = $this->request->getArguments();
$selectedAutohaus = $arguments['autohaus'];
$selectedAbteilung = $arguments['abteilung'];
if ($selectedAbteilung == null && $selectedAutohaus == null) {
echo("Bitte ein Autohaus auswählen / eine Abteilung.");
} else if ($selectedAbteilung == null) {
$autohausResult = $this->mitarbeiterRepository->findAutohaus($selectedAutohaus);
$this->view->assign('autohausResult', $autohausResult);
} else {
$mitarbeiterResult = $this->mitarbeiterRepository->findByFilter($selectedAutohaus, $selectedAbteilung);
$this->view->assign('mitarbeiterResult', $mitarbeiterResult);
}
$this->contentObj = $this->configurationManager->getContentObject();
$images=$this->getFileReferences($this->contentObj->data['uid']);
$this->view->assign('images', $images);
}
}
//MY REPOSITORY
<?php
namespace Formschoen\Mitarbeiterajax\Domain\Repository;
/**
* The repository for Mitarbeiters
*/
class MitarbeiterRepository extends \TYPO3\CMS\Extbase\Persistence\Repository
{
/**
* #param $selectedAutohaus
* #param $selectedAbteilung
*/
public function findByFilter($selectedAutohaus,$selectedAbteilung){
$query = $this->createQuery();
$result = $query->matching($query->logicalAnd(
$query->equals('autohausName', $selectedAutohaus),
$query->equals('abteilung', $selectedAbteilung)
))
->execute();
return $result;
}
/**
* #param $uid
*/
public function findAutohaus($uid)
{
$queryBuilder = $this->objectManager->get(\TYPO3\CMS\Core\Database\ConnectionPool::class)
->getConnectionForTable('tx_ajaxselectlist_domain_model_optionrecord')->createQueryBuilder();
$queryBuilder
->select('*')
->from('tx_ajaxselectlist_domain_model_optionrecord')
->where(
$queryBuilder->expr()->eq('uid', $queryBuilder->createNamedParameter($uid))
);
$result = $queryBuilder->execute()->fetchAll();
if ($returnRawQueryResult) {
$dataMapper = $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\Mapper\DataMapper::class);
return $dataMapper->map($this->objectType, $result);
}
return $result;
}
}
Why dont you just replace this
$autohausResult = $this->mitarbeiterRepository->findAutohaus($selectedAutohaus);
with this
$autohausResult = $this->optionRecordRepository->findByUid($selectedAutohaus);
This way TYPO3 will construct the Models and you will get the image they way you want it
so, I have a performance issue with my extbase plugin.
The scenario is such:
I have 4 database tables with data for artists, artworks, exhibitions and publications.
Exhibitions can have artists, artworks and publications as mm relations.
publications and artwork can have artists as mm relations.
In my Model Classes I have those relations as ObjectStorage and use simple findAll() Method for my List View.
So if I get to the Exhibition List View I get every Exhibition and their related Artists and all related Artworks/Publications/Exhibitions of that Artist.
The performance is really bad and a not cached page needs almost a full minute to load.
And this is all because of the heavy data load from the db.
I only need the MM relations on the first level and not further. Is there anyway to config this?
Classes\Domain\Model\Exhibition.php
class Exhibition extends AbstractEntity
{
/**
* #var string
*/
protected $name = '';
/**
* #var string
*/
protected $location = '';
/**
* artists
*
* #var ObjectStorage<\Vendor\Project\Domain\Model\Artist>
* #TYPO3\CMS\Extbase\Annotation\ORM\Lazy
*/
protected $artists = null;
/**
* artworks
*
* #var ObjectStorage<\Vendor\Project\Domain\Model\Artwork>
* #TYPO3\CMS\Extbase\Annotation\ORM\Lazy
*/
protected $artworks;
/**
* publications
*
* #var ObjectStorage<\Vendor\Project\Domain\Model\Publication>
* #TYPO3\CMS\Extbase\Annotation\ORM\Lazy
*/
protected $publications;
/**
* Fal media items
*
* #var \TYPO3\CMS\Extbase\Persistence\ObjectStorage<\TYPO3\CMS\Extbase\Domain\Model\FileReference>
* #TYPO3\CMS\Extbase\Annotation\ORM\Lazy
*/
protected $falMedia;
public function __construct(string $name = '', string $description = '', string $location = '')
{
$this->setName($name);
$this->setLocation($location);
}
/**
* #param string $name
*/
public function setName(string $name): void
{
$this->name = $name;
}
/**
* #return string
*/
public function getName(): string
{
return $this->name;
}
/**
* #return string
*/
public function getLocation(): string
{
return $this->location;
}
/**
* #param string $location
*/
public function setLocation(string $location): void
{
$this->location = $location;
}
/**
* Returns the artist
*
* #return ObjectStorage<\Vendor\Project\Domain\Model\Artist> $artists
*/
public function getArtists()
{
return $this->artists;
}
/**
* Sets the artist
*
* #param ObjectStorage<\Vendor\GKG\Domain\Model\Artist> $artists
* #return void
*/
public function setArtists(ObjectStorage $artists)
{
$this->artists = $artists;
}
/**
* #param $artworks
*/
public function setArtworks($artworks)
{
$this->artworks = $artworks;
}
/**
* #return ObjectStorage
*/
public function getArtworks()
{
return $this->artworks;
}
/**
* Sets the publications
*
* #param ObjectStorage<\Vendor\Project\Domain\Model\Publication> $oublications
* #return void
*/
public function setPublications(ObjectStorage $publications)
{
$this->publications = $publications;
}
/**
* Returns the publications
*
* #return ObjectStorage<\Vendor\Project\Domain\Model\Publication> $publications
*/
public function getPublications()
{
return $this->publications;
}
/**
* Get the Fal media items
*
* #return \TYPO3\CMS\Extbase\Persistence\ObjectStorage
*/
public function getFalMedia()
{
return $this->falMedia;
}
}
This gets all the Artist data in which all related data is fetched as well (artwork, exhibition and publication). And this is a heavy overload :/
I tried to write my own query and only select the values I need in my frontend:
Classes\Domain\Repository\ExhibitionRepository.php
public function findExhibitions()
{
$languageAspect = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance
(\TYPO3\CMS\Core\Context\Context::class)->getAspect('language');
$sys_language_uid = $languageAspect->getId();
$query = $this->createQuery();
$query->getQuerySettings()->setRespectSysLanguage(true);
$query->statement( "
SELECT DISTINCT e.name, e.uid, e.location, e.fal_media, a.name, a.uid
FROM tx_project_domain_model_exhibition e
LEFT JOIN tx_project_exhibitions_artists_mm
ON tx_project_exhibitions_artists_mm.uid_local = e.uid
LEFT JOIN tx_project_domain_model_artist a
ON tx_project_exhibitions_artists_mm.uid_foreign = a.uid
WHERE e.sys_language_uid = $sys_language_uid
GROUP BY tx_project_exhibitions_artists_mm.uid_local
" );
return $query->execute();
}
But with this approach I’m not able to get the relation data to my assigned view variable inside my Controller. Only the exhibition related stuff.
Classes\Controller\ExhibitionController.php
public function indexAction()
{
$queryResult = $this->exhibitionRepository->findExhibitions();
$this->view->assign('exhibitions', $queryResult);
}
Any insight and advice on how to tackle this problem and only get the needed Data and not everything from the ObjectStorage?
Thanks in advance and best regards
It looks like your query cost is very high with all the JOINS and without a condition on a indexed column.
You could check it with an EXPLAIN PLAN(MySQL) / EXECUTION PLAN(MS).
Set condition with an index to boost Performance
Rather using the Comparing operations leads to Performance.
https://docs.typo3.org/m/typo3/book-extbasefluid/main/en-us/6-Persistence/3-implement-individual-database-queries.html
Another performance boost is to use Ajax, just search for "TYPO3 Ajax":
get an identifier and display it in the Frontend:
SELECT DISTINCT e. uid, e.name FROM tx_project_domain_model_exhibition
On identifier click (name or whatever) make a call of the AjaxController.php:
...
$this->exhibitionRepository->findByUid($uid);
...
or make your own repository comparing
...
$query->matching(
$query->logicalAnd(
$query->equals('uid', $uid),
$query->equals('name', $name)
)
);
...
show the data on a Modal Window,Accordion or a new View.
I've setup my server with Yii2 and Humhub ext,
What i'm trying to do is set a rest api to it , but I get 500 Internal server error :
"message": "Cannot declare class humhub\modules\content\models\Content, because the name is already in use",
"file": "***\content\models\Content.php",
The first class is :
<?php
namespace app\models;
use Yii;
include '../humhub/modules/content/models/content.php';
class Content extends \humhub\modules\content\models\Content
{
public function getPosts()
{
return $this->hasMany(Post::className(), ['id' => 'object_id']);
}
}
The second class is (pretty big):
<?php
/**
* #link https://www.humhub.org/
* #copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* #license https://www.humhub.com/licences
*/
namespace humhub\modules\content\models;
include __DIR__ .'/../../../modules\content\models\ContentDeprecated.php';
use Yii;
use humhub\modules\user\components\PermissionManager;
use yii\base\Exception;
use yii\helpers\Url;
use humhub\modules\user\models\User;
use humhub\modules\space\models\Space;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\components\ContentContainerActiveRecord;
use humhub\modules\content\permissions\ManageContent;
use yii\rbac\Permission;
/**
* This is the model class for table "content".
*
*
* The followings are the available columns in table 'content':
* #property integer $id
* #property string $guid
* #property string $object_model
* #property integer $object_id
* #property integer $visibility
* #property integer $pinned
* #property string $archived
* #property string $created_at
* #property integer $created_by
* #property string $updated_at
* #property integer $updated_by
* #property ContentContainer $contentContainer
*
* #since 0.5
*/
class Content extends ContentDeprecated
{
/**
* A array of user objects which should informed about this new content.
*
* #var array User
*/
public $notifyUsersOfNewContent = [];
/**
* #var int The private visibility mode (e.g. for space member content or user profile posts for friends)
*/
const VISIBILITY_PRIVATE = 0;
/**
* #var int Public visibility mode, e.g. content which are visibile for followers
*/
const VISIBILITY_PUBLIC = 1;
/**
* #var int Owner visibility mode, only visible for contentContainer + content owner
*/
const VISIBILITY_OWNER = 2;
/**
* #var ContentContainerActiveRecord the Container (e.g. Space or User) where this content belongs to.
*/
protected $_container = null;
/**
* #inheritdoc
*/
public function behaviors()
{
return [
[
'class' => \humhub\components\behaviors\PolymorphicRelation::className(),
'mustBeInstanceOf' => array(ContentActiveRecord::className()),
],
[
'class' => \humhub\components\behaviors\GUID::className(),
],
];
}
/**
* #inheritdoc
*/
public static function tableName()
{
return 'content';
}
/**
* #inheritdoc
*/
public function rules()
{
return [
[['object_id', 'visibility', 'pinned'], 'integer'],
[['archived'], 'safe'],
[['guid'], 'string', 'max' => 45],
[['object_model'], 'string', 'max' => 100],
[['object_model', 'object_id'], 'unique', 'targetAttribute' => ['object_model', 'object_id'], 'message' => 'The combination of Object Model and Object ID has already been taken.'],
[['guid'], 'unique']
];
}
/**
* Returns a Content Object by given Class and ID
*
* #param string $className Class Name of the Content
* #param int $id Primary Key
*/
public static function Get($className, $id)
{
$content = self::findOne(['object_model' => $className, 'object_id' => $id]);
if ($content != null) {
return $className::findOne(['id' => $id]);
}
return null;
}
/**
* #inheritdoc
*/
public function beforeSave($insert)
{
if ($this->object_model == "" || $this->object_id == "") {
throw new Exception("Could not save content with object_model or object_id!");
}
// Set some default values
if (!$this->archived) {
$this->archived = 0;
}
if (!$this->visibility) {
$this->visibility = self::VISIBILITY_PRIVATE;
}
if (!$this->pinned) {
$this->pinned = 0;
}
if ($insert) {
if ($this->created_by == "") {
$this->created_by = Yii::$app->user->id;
}
}
$this->stream_sort_date = new \yii\db\Expression('NOW()');
if ($this->created_by == "") {
throw new Exception("Could not save content without created_by!");
}
return parent::beforeSave($insert);
}
/**
* #inheritdoc
*/
public function afterSave($insert, $changedAttributes)
{
$contentSource = $this->getPolymorphicRelation();
foreach ($this->notifyUsersOfNewContent as $user) {
$contentSource->follow($user->id);
}
if ($insert && !$contentSource instanceof \humhub\modules\activity\models\Activity) {
if ($this->container !== null) {
$notifyUsers = array_merge($this->notifyUsersOfNewContent, Yii::$app->notification->getFollowers($this));
\humhub\modules\content\notifications\ContentCreated::instance()
->from($this->user)
->about($contentSource)
->sendBulk($notifyUsers);
\humhub\modules\content\activities\ContentCreated::instance()
->about($contentSource)->save();
Yii::$app->live->send(new \humhub\modules\content\live\NewContent([
'sguid' => ($this->container instanceof Space) ? $this->container->guid : null,
'uguid' => ($this->container instanceof User) ? $this->container->guid : null,
'originator' => $this->user->guid,
'contentContainerId' => $this->container->contentContainerRecord->id,
'visibility' => $this->visibility,
'contentId' => $this->id
]));
}
}
return parent::afterSave($insert, $changedAttributes);
}
/**
* #inheritdoc
*/
public function afterDelete()
{
// Try delete the underlying object (Post, Question, Task, ...)
$this->resetPolymorphicRelation();
if ($this->getPolymorphicRelation() !== null) {
$this->getPolymorphicRelation()->delete();
}
parent::afterDelete();
}
/**
* Returns the visibility of the content object
*
* #return Integer
*/
public function getVisibility()
{
return $this->visibility;
}
/**
* Checks if the content visiblity is set to public.
*
* #return boolean
*/
public function isPublic()
{
return $this->visibility == self::VISIBILITY_PUBLIC;
}
/**
* Checks if the content visiblity is set to private.
*
* #return boolean
*/
public function isPrivate()
{
return $this->visibility == self::VISIBILITY_PRIVATE;
}
/**
* Checks if the content object is pinned
*
* #return Boolean
*/
public function isPinned()
{
return ($this->pinned);
}
/**
* Pins the content object
*/
public function pin()
{
$this->pinned = 1;
//This prevents the call of beforesave, and the setting of update_at
$this->updateAttributes(['pinned']);
}
/**
* Unpins the content object
*/
public function unpin()
{
$this->pinned = 0;
$this->updateAttributes(['pinned']);
}
/**
* Checks if the user can pin this content.
* This is only allowed for workspace owner.
*
* #return boolean
*/
public function canPin()
{
if ($this->isArchived()) {
return false;
}
return $this->getContainer()->permissionManager->can(new ManageContent());
}
/**
* Creates a list of pinned content objects of the wall
*
* #return Int
*/
public function countPinnedItems()
{
return Content::find()->where(['content.contentcontainer_id' => $this->contentcontainer_id, 'content.pinned' => 1])->count();
}
/**
* Checks if current content object is archived
*
* #return boolean
*/
public function isArchived()
{
return $this->archived || ($this->getContainer() !== null && $this->getContainer()->isArchived());
}
/**
* Checks if the current user can archive this content.
* The content owner and the workspace admin can archive contents.
*
* #return boolean
*/
public function canArchive()
{
// Disabled on user profiles, there is no stream filter available yet.
if ($this->getContainer() instanceof User) {
return false;
}
return $this->getContainer()->permissionManager->can(new ManageContent());
}
/**
* Archives the content object
*/
public function archive()
{
if ($this->canArchive()) {
if ($this->isPinned()) {
$this->unpin();
}
$this->archived = 1;
if (!$this->save()) {
throw new Exception("Could not archive content!" . print_r($this->getErrors(), 1));
}
}
}
/**
* Unarchives the content object
*/
public function unarchive()
{
if ($this->canArchive()) {
$this->archived = 0;
$this->save();
}
}
/**
* Returns the url of this content.
*
* By default is returns the url of the wall entry.
*
* Optionally it's possible to create an own getUrl method in the underlying
* HActiveRecordContent (e.g. Post) to overwrite this behavior.
* e.g. in case there is no wall entry available for this content.
*
* #since 0.11.1
*/
public function getUrl()
{
if (method_exists($this->getPolymorphicRelation(), 'getUrl')) {
return $this->getPolymorphicRelation()->getUrl();
}
return Url::toRoute(['/content/perma', 'id' => $this->id]);
}
/**
* Sets container (e.g. space or user record) for this content.
*
* #param ContentContainerActiveRecord $container
* #throws Exception
*/
public function setContainer(ContentContainerActiveRecord $container)
{
$this->contentcontainer_id = $container->contentContainerRecord->id;
$this->_container = $container;
}
/**
* Returns the content container (e.g. space or user record) of this content
*
* #return ContentContainerActiveRecord
* #throws Exception
*/
public function getContainer()
{
if ($this->_container != null) {
return $this->_container;
}
if ($this->contentContainer !== null) {
$this->_container = $this->contentContainer->getPolymorphicRelation();
}
return $this->_container;
}
/**
* Relation to ContentContainer model
* Note: this is not a Space or User instance!
*
* #since 1.1
* #return \yii\db\ActiveQuery
*/
public function getContentContainer()
{
return $this->hasOne(ContentContainer::className(), ['id' => 'contentcontainer_id']);
}
/**
* Checks if the given user can edit this content.
*
* A user can edit a content if one of the following conditions are met:
*
* - User is the owner of the content
* - User is system administrator and the content module setting `adminCanEditAllContent` is set to true (default)
* - The user is granted the managePermission set by the model record class
* - The user meets the additional condition implemented by the model records class own `canEdit()` function.
*
* #since 1.1
* #param User $user
* #return bool can edit this content
*/
public function canEdit($user = null)
{
if (Yii::$app->user->isGuest) {
return false;
}
if ($user === null) {
$user = Yii::$app->user->getIdentity();
}
// Only owner can edit his content
if ($user !== null && $this->created_by == $user->id) {
return true;
}
// Global Admin can edit/delete arbitrarily content
if (Yii::$app->getModule('content')->adminCanEditAllContent && $user->isSystemAdmin()) {
return true;
}
/* #var $model ContentActiveRecord */
$model = $this->getPolymorphicRelation();
// Check additional manage permission for the given container
if ($model->hasManagePermission() && $this->getContainer() && $this->getContainer()->getPermissionManager($user)->can($model->getManagePermission())) {
return true;
}
// Check if underlying models canEdit implementation
// ToDo: Implement this as interface
if (method_exists($model, 'canEdit') && $model->canEdit($user)) {
return true;
}
return false;
}
/**
* Checks the given $permission of the current user in the contents content container.
* This is short for `$this->getContainer()->getPermissionManager()->can()`.
*
* #param $permission
* #param array $params
* #param bool $allowCaching
* #see PermissionManager::can()
* #since 1.2.1
* #return bool
*/
public function can($permission, $params = [], $allowCaching = true)
{
return $this->getContainer()->getPermissionManager()->can($permission, $params, $allowCaching);
}
/**
* Checks if user can view this content.
*
* #since 1.1
* #param User $user
* #return boolean can view this content
*/
public function canView($user = null)
{
if (!$user && !Yii::$app->user->isGuest) {
$user = Yii::$app->user->getIdentity();
}
// Check Guest Visibility
if (!$user) {
return $this->checkGuestAccess();
}
// Public visible content
if ($this->isPublic()) {
return true;
}
// Check system admin can see all content module configuration
if ($user->isSystemAdmin() && Yii::$app->getModule('content')->adminCanViewAllContent) {
return true;
}
if ($this->isPrivate() && $this->getContainer()->canAccessPrivateContent($user)) {
return true;
}
return false;
}
/**
* Determines if a guest user is able to read this content.
* This is the case if all of the following conditions are met:
*
* - The content is public
* - The `auth.allowGuestAccess` module setting is enabled
* - The space or profile visibility is set to VISIBILITY_ALL
*
* #return bool
*/
public function checkGuestAccess()
{
if(!$this->isPublic() || !Yii::$app->getModule('user')->settings->get('auth.allowGuestAccess')) {
return false;
}
// Check container visibility for guests
return ($this->container instanceof Space && $this->container->visibility == Space::VISIBILITY_ALL)
|| ($this->container instanceof User && $this->container->visibility == User::VISIBILITY_ALL);
}
/**
* Updates the wall/stream sorting time of this content for "updated at" sorting
*/
public function updateStreamSortTime()
{
$this->updateAttributes(['stream_sort_date' => new \yii\db\Expression('NOW()')]);
}
}
As you can see the first class extends the second one , I'm rather new to php but i'm guessing that's the issue
UPDATE : I tried using the "use class as " and still the same error , I also tried changing the name of the first class to Content1 just to check and still the same .
The problem occours in the second class from the error report
This is a recurring error in a few places in the server I figure I will solve it here and the rest will be the same ,
Many Thanks!
You included file with exacly same class name, so you have 2 class declarations with name Content in this file. Easiest ways to fix it:
Change one of class name
Start using Yii2 autloader, if you need to include something - there's something wrong in your code. You should be able to access
class only by using namespace. There's small conditions you have to
met:
Each class must be under a namespace (e.g. foo\bar\MyClass)
Each class must be saved in an individual file whose path is determined by the following algorithm:
// $className is a fully qualified class name without the leading backslash
$classFile = Yii::getAlias('#' . str_replace('\\', '/', $className) . '.php');
More about Yii2 autloading: Class Autoloading
For my project, I have a workspace (kind of a user) with many projects and I am wondering if there is a way to override the default Doctrine query for when I call $workspace->getProjects() to only fetch the active projects only (not the archived one). This way I won't have to filter my collection and it will reduce the size of the returned data from the database.
/**
* Acme\DemoBundle\Entity\Workspace
*
* #ORM\Table()
* #ORM\Entity
*/
class Workspace {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
private $id;
/**
* #var ArrayCollection $projects
*
* #ORM\OneToMany(targetEntity="Project", mappedBy="workspace")
*/
private $projects;
/**
* Add projects
*
* #param Project $projects
* #return Workspace
*/
public function addProject( Project $projects ) {
$this->projects[] = $projects;
return $this;
}
/**
* Remove projects
*
* #param Project $projects
*/
public function removeProject( Project $projects ) {
$this->projects->removeElement( $projects );
}
/**
* Get projects
*
* #return Collection
*/
public function getProjects() {
return $this->projects;
}
You will have to write your own method in the Entity Repository Class.
http://symfony.com/doc/current/book/doctrine.html#custom-repository-classes
To do that, you can use criteria.
Here is an exemple from the doctrine doc, to adapt to your needs
use Doctrine\Common\Collections\Criteria;
$criteria = Criteria::create()
->where(Criteria::expr()->eq("birthday", "1982-02-17"))
->orderBy(array("username" => Criteria::ASC))
->setFirstResult(0)
->setMaxResults(20)
;
$birthdayUsers = $object-getUsers()->matching($criteria);
You can create some listener, and catch doctrine events: http://docs.doctrine-project.org/projects/doctrine1/en/latest/en/manual/event-listeners.html
And modify your query before execute as you wish;
Example from Doctrine docs, for custom hook on delete:
<?php
class UserListener extends Doctrine_EventListener
{
/**
* Skip the normal delete options so we can override it with our own
*
* #param Doctrine_Event $event
* #return void
*/
public function preDelete( Doctrine_Event $event )
{
$event->skipOperation();
}
/**
* Implement postDelete() hook and set the deleted flag to true
*
* #param Doctrine_Event $event
* #return void
*/
public function postDelete( Doctrine_Event $event )
{
$name = $this->_options['name'];
$event->getInvoker()->$name = true;
$event->getInvoker()->save();
}
/**
* Implement preDqlDelete() hook and modify a dql delete query so it updates the deleted flag
* instead of deleting the record
*
* #param Doctrine_Event $event
* #return void
*/
public function preDqlDelete( Doctrine_Event $event )
{
$params = $event->getParams();
$field = $params['alias'] . '.deleted';
$q = $event->getQuery();
if ( ! $q->contains( $field ) )
{
$q->from('')->update( $params['component'] . ' ' . $params['alias'] );
$q->set( $field, '?', array(false) );
$q->addWhere( $field . ' = ?', array(true) );
}
}
/**
* Implement preDqlDelete() hook and add the deleted flag to all queries for which this model
* is being used in.
*
* #param Doctrine_Event $event
* #return void
*/
public function preDqlSelect( Doctrine_Event $event )
{
$params = $event->getParams();
$field = $params['alias'] . '.deleted';
$q = $event->getQuery();
if ( ! $q->contains( $field ) )
{
$q->addWhere( $field . ' = ?', array(false) );
}
}
}
I think you can put your logic inside the getter method itself
public function getProjects() {
$filtered_projects = array()
foreach($this->projects as $project)
{
// Your logic here
// e.g.
// if($project->getIsActive()){
// $filtered_projects[] = $project;
// }
}
return $filtered_projects;
}
Goodday Stackoverflow,
I've implented the Captcha-helper in my project successfully. The image is being displayed, saved and what not, although the image itself is created again and again and again after every refresh. After 10 refreshes, my captcha folder contains 10 images.
Is this normal?
This is my code;
...
/**
* Method that returns the currently
* active Captcha code of the user.
*
* #access public
* #return string - user's captcha code
* #since v0.1.0.0
*/
public function get_captcha()
{
// Check for already existing captcha's.
if ($this->is_captcha())
{
// Get the captcha.
$data = $this->get_captcha_data();
}
else
{
// Create a new captcha.
if ($this->insert_captcha())
$data = $this->get_captcha_data();
}
// Set the values.
$captcha_vals = array(
'word' => $data['word'],
'img_path' => './media/sm_general/captcha/',
'img_url' => base_url().'media/sm_general/captcha/',
'img_width' => '175',
'img_height' => '60'
);
// Return the captcha.
return create_captcha($captcha_vals);
}
/**
* Method that returns the captcha data
* of a specific user.
*
* #access private
* #param string $field - (optional) specific to be returned data
* #return array/string - data of the captcha
* #since v0.1.0.0
*/
private function get_captcha_data($field='')
{
// Prepare the query.
$this->db->select('*');
$this->db->from('sm_sessions_captcha');
$this->db->where('ip_address',$this->input->ip_address());
$this->db->limit(1);
// Execute the query.
$query = $this->db->get();
// Get the result.
$result = $query->row_array();
// Return the data.
if ( ! empty($field))
return $result[$field];
else
return $result;
}
/**
* Method that returns a random word from
* the database.
*
* #access private
* #return string - randomly selected word
* #since v0.1.0.0
*/
private function get_word_random()
{
// Prepare the query.
$this->db->select('word');
$this->db->from('sm_sessions_captcha_words');
$this->db->order_by('word','RANDOM');
$this->db->limit(1);
// Execute the query.
$query = $this->db->get();
// Get the result.
$result = $query->row_array();
// Return the word.
return $result['word'];
}
/**
* Method that creates a new captcha image.
*
* #access private
* #return array
* #since v0.1.0.0
*/
private function insert_captcha()
{
// Prepare the query.
$data = array(
'captcha_time' => (time() + 7200),
'ip_address' => $this->input->ip_address(),
'word' => $this->get_word_random()
);
// Execute the query.
if ($this->db->insert('sm_sessions_captcha',$data))
return true;
else
return false;
}
/**
* Check if a captcha already exists.
*
* #access private
* #return boolean - exists or not
* #since v0.1.0.0
*/
private function is_captcha()
{
// Set the expiration time.
$expiration = time() - 7200;
// Remove all expired captchas.
$this->db->where('captcha_time <',$expiration);
$this->db->delete('sm_sessions_captcha');
// Prepare the query.
$this->db->select('*');
$this->db->from('sm_sessions_captcha');
$this->db->where('captcha_time >=',$expiration);
$this->db->where('ip_address',$this->input->ip_address());
$this->db->limit(1);
// Execute the query.
$query = $this->db->get();
// Return the existence.
if ($query->num_rows() == 1)
return true;
else
return false;
}
...
I have no idea if this is working as intended. Please enlighten me if I am mistaking.
Cheers.
This is normal, every refresh a new captcha image is generated, then CI runs a garbage collection, so you can set how much time the old captcha image should remain inside the folder by "expiration" value
http://ellislab.com/codeigniter/user-guide/helpers/captcha_helper.html
$cap = create_captcha($vals);
$this->session->set_userdata('time', $cap['time']);
Write in when data store in database.
Above that:
unlink(realpath('captcha').'/'.$this->session->userdata('time').'.jpg');