Jump to:

7935 Posts in 1536 Topics by 943 members

DataObjectManager Module

SilverStripe Forums » DataObjectManager Module » Preview: DataObjectManager module

Discuss the DataObjectManager module, and the related ImageGallery module.

Moderators: martimiz, UncleCheese, Sean, biapar, Willr, Ingo, swaiba, simon_w

Page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
Go to End
Author Topic: 60034 Views
  • Ben Gribaudo
    Avatar
    Community Member
    181 Posts

    Re: Preview: DataObjectManager module Link to this post

    Hi Uncle Cheese,

    I've run across a bug re ManyManyDataObjectManager's field list. Setting one up like this:

          $tablefield = new ManyManyDataObjectManager(
             $this,
             'Qualities',
             'QualityHomePage',
             array(
                'Title' => 'Quality',
                'Primary' => 'Primary'
             ),
             'getCMSFields_forPopup'
          );
          $tablefield->setParentClass('QuoteModel');
          $fields->addFieldToTab('Root.Main', $tablefield);


    causes a SQL error. The problem is that the field array contains a field name of "Primary", which is a MySQL reserved word. MySQL requires that reserved words be escaped when used as field names in SQL. This isn't being done. The query being run looks like:

    SELECT `SiteTree`.*, `QualityHomePage`.*, `SiteTree`.ID, if(`SiteTree`.ClassName,`SiteTree`.ClassName,'SiteTree') AS RecordClassName,
    Primary,
    IF(`QuoteModelID` IS NULL, '0', '1') AS Checked FROM `SiteTree` LEFT JOIN `QualityHomePage` ON `QualityHomePage`.ID = `SiteTree`.ID LEFT JOIN `QuoteModel_Qualities` ON (`SiteTree`.`ID` = `QualityHomePageID` AND `QuoteModelID` = '4') WHERE (`SiteTree`.ClassName IN ('QualityHomePage')) GROUP BY `SiteTree`.ID ORDER BY Sort LIMIT 0, 10

    If I change the field type to ManyManyComplexTableField but don't otherwise change the arguments passed to the field's constructor, the resulting query looks like:

    SELECT `SiteTree`.*, `QualityHomePage`.*, `SiteTree`.ID, if(`SiteTree`.ClassName,`SiteTree`.ClassName,'SiteTree') AS RecordClassName,
    `Primary`,
    IF(`QuoteModelID` IS NULL, '0', '1') AS Checked FROM `SiteTree` LEFT JOIN `QualityHomePage` ON `QualityHomePage`.ID = `SiteTree`.ID LEFT JOIN `QuoteModel_Qualities` ON (`SiteTree`.`ID` = `QualityHomePageID` AND `QuoteModelID` = '4') WHERE (`SiteTree`.ClassName IN ('QualityHomePage')) GROUP BY `SiteTree`.ID ORDER BY Sort LIMIT 0,10

    So, ManyManyComplexTableField properly escapes the field with tick marks while ManyManyDataObjectManager doesn't. Would you be willing to fix this?

    Thank you,
    Ben

  • UncleCheese
    Avatar
    4085 Posts

    Re: Preview: DataObjectManager module Link to this post

    @Ben - Thanks for flushing that out. I'll look into it. My guess is that it goes all the way up to DOM, since MMDOM differs only marginally from MMCTF.

    @robinp - My apologies. In my previous message, I had mixed up your name with cmswarrior. The message to you was directed at him/her, and vice-versa. Glad you got it working. I'd like to make that a config setting but it's a little tricky converting PHP to Javascript. Did you find a setting that was more comfortable for you?

  • micahsheets
    Avatar
    Community Member
    164 Posts

    Re: Preview: DataObjectManager module Link to this post

    For anyone who cares, here is the solution I came up with for allowing a Prev and Next navigation of Testimonials while having the initial one be random.

    I added this code to my TestimonialPage.php

       public function currentTestimonial() {
          $testimonials = DataObject::get("Testimonial","ClassName = 'Testimonial'");
          $tID = (int)$this->urlParams['Action'];
          if ($tID > $testimonials->Count()) {
             $tID = 1;
          }
          else if ($tID <= 0){
             $tID = $testimonials->Count();
          }
          
          if ($tID == 0){
             $tID = rand(1,$testimonials->Count());
             return $testimonials->find('ID',$tID);
          }
          else {
             return $testimonials->find('ID',$tID);
          }
       }
       
       protected function adjacentTestimonial($dir){
          $testimonials = DataObject::get("Testimonial","ClassName = 'Testimonial'");
          $i = (int)$this->urlParams['Action'];
          $t = $dir == "next" ? $i+1 : $i-1;
          if ($t > $testimonials->Count()) {
             $t = 1;
          }
          else if ($t <= 0){
             $t = $testimonials->Count();
          }
          return "/testimonials/$t";
       }
       
       public function NextTestimonial()
       {
          return $this->adjacentTestimonial("next");
       }

       public function PrevTestimonial()
       {
          return $this->adjacentTestimonial("prev");
       }

    Works like a charm for my purposes. I don't know if there are any security issues with this. I did set it so that if someone types an incorrect value into the Action urlParam it will just put them at the first Testimonial.

  • vstrazz
    Avatar
    Community Member
    63 Posts

    Re: Preview: DataObjectManager module Link to this post

    @ UncleCheese I have tried to create a DataObjectManager in page.php that could be used in every page created in the CMS and all Sub classes of page.php

    The problem is on regular pages the objects for that page appear in the manager correctly and any other page types all objects created in the CMS appear in the manager.

    any ideas?

    I did notice by adding

    static $has_one = array (
    "Home" => "HomePage",
    );

    to the "Feature" made the HomePage page type only show it's own objects.

    here's the code

    page.php

    static $has_many = array(
    "Featured" => "Feature"
    );

    function getCMSFields() {
          $fields = parent::getCMSFields();

    $fields->addFieldToTab("Root.Content.Features", new DataObjectManager(
    $this,
    'Featured',
    'Feature',
    array(
    'Title' => 'Title',
    'Redirect'=> 'Links to'
    ),
    'getCMSFields_forPopup'
    ));
          
          return $fields;
    }

    feature.php

    class Feature extends DataObject
    {
    static $db = array (
    'Title' => 'Text',
    'Content' => 'HTMLText',
    "Redirect" => "Varchar(255)",
    "External" => "Boolean"

    );

    static $has_one = array (
    'Pager' => 'Page',
    "Home" => "HomePage",
    "FeatureImage" => "Image",
    "LinkTo" => "SiteTree"
    );

    public function getCMSFields_forPopup()
    {
    return new FieldSet(
    new TextField('Title'),
    new TextareaField('Content'),
    new TextField("Redirect", "Link to this page"),
    new CheckboxField("External", "Open link in New Window?"),
    new ImageField("FeatureImage")
    );
    }
    }

  • robinp
    Avatar
    Community Member
    33 Posts

    Re: Preview: DataObjectManager module Link to this post

    @UncleCheese yes I found setting that is working well for the large data based

  • UncleCheese
    Avatar
    4085 Posts

    Re: Preview: DataObjectManager module Link to this post

    @vstrazz - If you want to use your dataobject manager on a subclass, make sure you set the parent class to clear up the ambiguity.

    $manager->setParentClass("Page");

  • hu
    Avatar
    Community Member
    21 Posts

    Re: Preview: DataObjectManager module Link to this post

    @UncleCheese: Can you please change this in FileDataObjectManager.php. The getUploadFolder() {...} never get called.

    public function UploadForm() {
       // Sync up the DB
       singleton('Folder')->syncChildren();
       $className = $this->sourceClass();
       $childData = new $className();
       $validator = $this->getValidatorFor($childData);
       if($this->Can('upload')) {
          SWFUploadConfig::addPostParams(array(
             'dataObjectClassName' => $this->sourceClass(),
             'dataObjectFieldName' => $this->dataObjectFieldName,
             'fileFieldName' => $this->fileFieldName,
             'fileClassName' => $this->fileClassName,
             'parentIDName' => $this->getParentIdName( $this->getParentClass(), $this->sourceClass() ),
             'controllerID' => $this->controllerID,
    'OverrideUploadFolder' => $this->uploadFolder
             'OverrideUploadFolder' => $this->getUploadFolder()
          ));
    }

  • hu
    Avatar
    Community Member
    21 Posts

    Re: Preview: DataObjectManager module Link to this post

    @UncleCheese: And what do you think about the following feature:

    ...
    $managerImages = new ImageDataObjectManager(
    ...
    );      
    $managerImages->setUploadFolder('Uploads/[ID]');
    ...

    FileDataObjectManager.php

    public function getUploadFolder()
    {
       return str_replace("[ID]", $this->controllerID, $this->uploadFolder);
    }

    60034 Views
Page: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.