Jump to content

creativejay

Members
  • Posts

    259
  • Joined

  • Last visited

Posts posted by creativejay

  1. Hello all. I have a question that I know must have a simple answer but I've been unable to find it in the forums or documentation.

    I want to throw a styled bit of markup around the links to switch language on a given page, but I don't want to output the markup if there is only the default language available and therefor no links to output.

    I was approaching this by trying to count the languages for the page which are marked in the settings tab as active, but I can't seem to find the correct syntax for that.

    I'm using the basic recommended method to generate the links but nothing in these lines helped me find the answer.

    foreach($languages as $language) {
    	
    	  // if user is already viewing the page in this language, skip it
    	  if($language->id == $savedLanguage->id) continue;
    	
    	  // if this page isn't viewable (active) for the language, skip it
    	  if(!$page->viewable($language)) continue;
    	
    	  // set the user's language, so that the $page->url and any other
    	  // fields we access from it will be reflective of the $language
    	  $user->language = $language;
    	
    	  // output a link to this page in the other language
    	  $language .= "<li class='language' style='float: left; display: inline; padding: 1em;'><a href='$page->url'>$language->title</a></li>";
    	}

    I tried count($languages) but that includes inactive languages in the count. I tried count($page->viewable($language)) and a few other inventive lines with no results until I decided to finally just ask here. ;)

    I'm of course open to using some other calculation to determine whether to output my code.

    Appreciate the help!

  2. Further down the rabbit hole..

    I'm still getting an error at line 128 so anything beyond that I haven't discovered yet. The error I'm getting is that $specification isn't defined (I expected it to be held as part of the key/value pair). Is that because we're within the brackets of the foreach that builds the array?

    	$children = $page->children;
    	$iterationNum = count( $children ); 
    		echo $iterationNum . " model";
    		if($iterationNum > 1) {echo "s";}
    		echo " in this series";
    		
    	foreach( $children as $key => $model ) { // numbers the children starting from 0, and $model becomes their page ID
    		echo "<ul>";
            foreach( $model as $specification => $specvalue ) { // each child becomes an array containing the field names and values
                if($specvalue != '') {
    	            $bySpec = array_reduce($children->getArray(), function($carry, $child){
    		            $value = $child->get($specification);
    	  $carry[$value][] = $child;
    	  return $carry;
    	  echo count( $carry );
    	}, array());
     
    	$toTextBlocks = array_map(function($field, $children){
    	  $childrenPA = (new PageArray)->import($children);
    	  return "$field (" . $children->implode(", ", "title") . ")";
    	}, array_keys($bySpec), $bySpec);
    	 
    	$line = implode(", ", $toTextBlocks);
                }
        }
    

    To describe what I'm trying to do: I want to cycle through the children of a page (sometimes it's going to be one. Typical is 2 - 8. There's one product series that includes over 180 possible items, though), and find the pertinent specs (the ones with values). I want to see which specs are the same for all products (I can't wait for pages to inherit values from a parent!) and then display those as simply as possible. Where a child under the series page doesn't have a value for a field that a sibling does, I want to indicate that one is an exception (or if only one does, that is listed as "(XXXX only)".

    Most of my fields are text fields, but some are integers, others are options, and occasionally we have one that's a Page type, or an image.

    I guess I would also need to figure out a way to omit some of these fields intentionally (f.ex. ones that will be addressed separately, or I want to keep hidden).

    At the bottom of the page, I plan to also display a table for each child in the series, with a sort of cross comparison of only those specs that differ.

    Am I totally off my nut to try and build this in this manner?

  3. For the simple minded this would be the foreach version that does the same. ;)

    $colors = array();
    $childrenByColor = array();
    
    foreach($children as $child) $colors[$child->color][] = $child;
    
    foreach($colors as $color => $items) {
        $childrenByColor[] = "$color (" . $items->implode(",", "title") . ")";
    }
    
    $line = implode(", ", $childrenByColor);

    Which is closer to how I might have naturally gone, but once I really get into the hundreds of lines for each Series page, won't I be better off with something more like what we developed above? As I'm still a beginner I constantly worry that I could be writing more efficient code, and now with the scale of this site being as large as it is, in terms of fields per product, and with all the field values I have to consider from isset/true-false/count and so forth, I want to build this with a solid foundation.

    Actually what I figure I really ought to do is double down and create a function for an include that I can call per field (there might be two or three types, depending on the data), to make that 'shorter is better' standard apply, at least to my template page. First I just want to get it outputting as intended, though.

    Now I'm trying to sort out my logic in the event that one of the children has a blank field (a blank field still creates a key meaning (count($byPrice_emea_eur) > 1) is still triggered).

  4. Essentially we're doing this in the array_reduce()

    [Page, Page, Page]
    
    =>
    
    [
      'key' => [Page, Page],
      'key2' => [Page]
    ]
    

    So just count how many items the resulting array has. If 1 show only the key, otherwise do the array_map().

    I think the argument about more structure (compared to loops) is far more valid than the "shorter is better" one. I'm using Laravel's collection package via https://github.com/tightenco/collect with some additional hooked in functions and especially such transformation tasks are so much clearer to create as well as to read.

    Ah, I understand now. Thank you!

    Really, it bears repeating: thank you!

    Here's the code that you helped me build:

     $byPrice_emea_eur = array_reduce($children->getArray(), function($carry, $child){
    	  $carry[$child->price_emea_eur][] = $child;
    	  return $carry;
    	}, array());
    	
    	
     if(count($byPrice_emea_eur) > 1) {
    		$toTextBlocks = array_map(function($price_emea_eur, $children){
    		  $childrenPA = (new PageArray)->import($children);
    		  return "€ $price_emea_eur (" . $childrenPA->implode(", ", "title") . ")";
    		}, array_keys($byPrice_emea_eur), $byPrice_emea_eur);
    		
    		$line = implode(", ", $toTextBlocks);
    	} else { 
    		$line = "€" . $page->child->price_emea_eur;
    	}
    	echo "Price: " . $line . "";
    
  5. Not bad at all, you just need to use $child->field->title (or ->value, if you're using those). It's just that the key needs to be some sting or int.

    And replace line 9 with this. Missed the PA part of the variable. Also the second argument of the implode call is supposed to be the "title" of your children or you'll just end up with something like this: green (green, green, green), blue (blue, blue)

    return "$price_emea_eur (" . $childrenPA->implode(", ", "title") . ")";

    Thanks! that PA bit must have been what threw me when I just tried to grab ->title for the array, too.

    It's working now! So I have two pages with fields with different values, $list gives me XXX.XX (Page A), XXX.ZZ (Page B) - Perfect!

    When I change both pages to have the same value, it outputs XXX.XX (Page A, Page B). Which would be great if there were a XXX.YY (Page C). But when all (no matter the count 1 - 100) have the same value, I want to suppress the bit in the parenthesis. 

    I imagine I'd build an if statement that compared the values before deciding to build $toTextBlocks? But I don't quite understand where the contents are being compared now. Before line 5? Something to do with $carry?

    I promise I'm also trying to look this up on php.net as I go, but I'm a babe in the woods on this one.

  6. Make sure $child->prod_fiber_type is a string and not an object (page field?). 

    Ah yes, derp, thank you. I chose a bad field to start with. Field type Options, that one.

    Now here is my code (I'll sort out converting array values to strings later), using a text field. I get a call to a non object for the implode at line 9.

    $byPrice_emea_eur = array_reduce($children->getArray(), function($carry, $child){
    	  $carry[$child->price_emea_eur][] = $child;
    	  return $carry;
    	  echo count( $carry );
    	}, array());
    
    $toTextBlocks = array_map(function($price_emea_eur, $children){
      $childrenPA = (new PageArray)->import($children);
      return "$price_emea_eur (" . $children->implode(", ", "price_emea_eur") . ")";
    }, array_keys($byPrice_emea_eur), $byPrice_emea_eur);
    
    $line = implode(", ", $toTextBlocks);
    
    
  7. $byColor = array_reduce($children->getArray(), function($carry, $child){
      $carry[$child->color][] = $child;
      return $carry;
    }, array());
    
    $toTextBlocks = array_map(function($color, $children){
      $childrenPA = (new PageArray)->import($children);
      return "$color (" . $children->implode(", ", "title") . ")";
    }, array_keys($byColor), $byColor);
    
    $line = implode(", ", $toTextBlocks);
    

    I receive an illegal offset type error on  the following

     $byProd_fiber_type = array_reduce($children->getArray(), function($carry, $child){
      $carry[$child->prod_fiber_type][] = $child; // ** error reported here **
      return $carry;
      echo count( $carry );
    }, array());
    
    $toTextBlocks = array_map(function($title, $children){
      $childrenPA = (new PageArray)->import($children);
      return "$prod_fiber_type (" . $children->implode(", ", "prod_fiber_type") . ")";
    }, array_keys($byProd_fiber_type), $byProd_fiber_type);
    
    $line = implode(", ", $toTextBlocks);
     

    Note I've changed "color" to "prod_fiber_type" since that was just a for instance (and I needed it to match a field to avoid a non-object error on the implode).

  8. I can really recommend http://adamwathan.me/refactoring-to-collections/ if you're curious (has a free sample as well). Brought a lot of light into all those functions and their usefulness. 

    Read through the sample. It's nice and plainly put. I could definitely see that helping me. In fact I can tell there are a lot of lessons in there that would improve the way I want to build this site, and it would be better to implement them here so close to the start. Not quite sure I can get that price approved, though.

    At least it gives me some hints about where I should start looking.

    Definitely sounds like arrays are not something I should be actively avoiding in favor of foreach loops!

    I wasn't able to get your code sample working before I quit for the day, but I'll be back at it in the morning.

    Thanks again!

  9. $byColor = array_reduce($children->getArray(), function($carry, $child){
      $carry[$child->color][] = $child;
      return $carry;
    }, array());
    
    $toTextBlocks = array_map(function($color, $children){
      $childrenPA = (new PageArray)->import($children);
      return "$color (" . $children->implode(", ", "title") . ")";
    }, array_keys($byColor), $byColor);
    
    $line = implode(", ", $toTextBlocks);
    

    Thank you! It'll take me a bit to wrap my head around this (I have never been strong in array logic), but I wanted to let you know I really appreciate the immediate reply and am trying to implement this.

  10. I am currently working on a site that lists about two hundred product series, which are displayed to the visitor as a web page.

    Beneath each of these Series pages are one or more children, and they may be nearly identical, with a few key differences.

    Does anyone have any advice on how I might run through the 'foreach' of the children on the Series' output page, and determine if the field values are the same or unique, and output the unique values while "merging" the common values?

    For example:

    Product Series A contains:

    • Model A - which has a "color" field value of "blue"
    • Model B - which has a "color" field value of "blue"
    • Model C - which has a "color" field value of "green"
    • Model D - which has a "color" field value of "red"

    So in this example, I'd want to list this information as:

    Product Series A

    [[bunches of info from the Series parent page's fields]]

    Specifications

          Color:      Blue (Models A and B), Green (Model C), or red (Model D)

    Or, if the values were all the same, it would list just the value without the model mentions. 

    Thanks in advance, even if you just have a direction to point me in, I'd appreciate any input. My brain is fried from all the crazy logic I've had to implement for this site already.  :frantics:

  11. On each page there is a Text field called "blog_name" which is currently using HTML Entity Encoder (htmlspecialchars) and Strip Markup Tags for formatting, and Strip Tags is checked on the Input tab.

    In the specific case that revealed the problem with apostrophes, the value of the field is set to "There's Snow One Like You"

  12. I'm using find in a sidebar to retrieve other pages in my site that share the same subject matter, as set in a text field. The trouble I'm running into is that, when that field's user entry contains apostrophes, find() does not return any results.

    if(!$polish) { $polish = wire('page');}	
    	$polish_year = $polish->blog_year;	
    	$polish_brand = $polish->blog_brand;	
    	$polish_collection = $polish->blog_polish_collection;
    	$polish_name = $polish->blog_name;
    	$postID = $polish->id;
    	$samePolishPosts = wire('pages')->find("template=blog-post, blog_polish_collection=$polish_collection, blog_brand=$polish_brand, blog_year=$polish_year, blog_name=$polish_name, blog_categories=1040, id!=$postID");
    
    

    Any tips?

  13. Thanks! I'm trying to make the site as fun as possible (it's a non-income-generating pet project), to make it emotionally rewarding for the authors that have volunteered to provide content.

    I'm attaching a screen shot of the post-login home page for an author (non-superuser). Fair warning, the color scheme may hurt the eyes. I'm going for quirky here.

    The challenge area is the 'ticket' system I was referring to.

    post-1266-0-31405400-1425998308_thumb.pn

    • Like 2
  14. I sorted out my earlier problem - turned out the head of the template included a base href call that was what was pushing comment submit to the home page. It's always the little things!

    Now that they're working, I'd like to send notification of new comments to the creator of the page the comments are submitted on. This will be different from page-to-page, so I don't want to put everyone's emails in the field's setting for notifications. I looked in the module for a spot to append a page-based value to the email send, but I didn't see it.

    What I'm trying to do exactly is better described in this thread I started for this and another email-hooking question.

    Thanks!

  15. Thanks for your reply and suggestions, nickie. I'm not sure this is what I'm trying to do.

    The comments are created using a FieldtypeComments field called challenge_comments. This is, I believe, one of Ryan's core modules.

    I can use FormBuilder to set up comments, but the function is already largely built-in. And I don't mind hooking to a page, but save doesn't seem the right place to do it in the first cast. The targeted user should get an email when a page is published meant for them (they are selected in a dropdown in the page creation template). This would happen in the admin back end.

    Then both the page creator and the targeted user should be notified when the other posts a comment to that published page (front end).

  16. In my ProcessBlog project, I have multiple authors and would like to send notifications on a couple different kinds of events.

    Situation 1:

    First, for blog_comments (a FieldtypeComments field) on the blog posts, I'd like to email the page's creator when there is a comment posted. Since the field's settings ask for a constant value for emails to send notifications to, I'm wondering if I should hook onto this field somehow, or if there's a syntax by which I can specify the superuser(s) and the person whose post it is (their email address is stored in their user page). I looked in the FieldtypeComments module for this and didn't see an obvious place where I could tack in code to append $createduser->email

    Situation 2 (& 2b):

    Second, I created a system of posts, sort of like a ticket system, by which users can communicate with each other (without having to know personal contact info). A user would issue one of these messages (by creating a page) and select the user from a Page field of qualified users. When they publish this page, I'd like to send an email to the user that was selected ($targeteduser->email).

    This page also has a comments field, and I'd like one user to get an email when the other user comments (similar to the first situation, except slightly more aware of who is posting and who is referenced in the page).

    Since both situations deal with page saves (saves generated by FieldtypeComments in situations 1 and 2b, and general page saves with publish in situation 2), I don't want to hook this to the page save or there might be excess emails going out. Not really familiar enough with hooks to know what else to consider, and nothing jumped out at me when I browsed the Captain Hook list.

    I imagine I'd create a new module, possibly 2, that looks at the page template and draws information from the fields in it, but I am a little stuck beyond that and would appreciate help with as much detail as anyone is willing to go into.

    Thanks in advance!

  17. Here is what's happening for me, the biggest problem I'm running into is that Redirects won't function properly with this setup.

    post-1266-0-93146700-1425650373_thumb.pn

    Here is the trailing slash setting of the template.

    post-1266-0-92873800-1425650410_thumb.pn

    Here is the Settings tab of a page using that template.

    post-1266-0-51719700-1425650458_thumb.pn

    Here is the system message upon saving.

    post-1266-0-64843400-1425650542_thumb.pn

    Setting up a redirect by selecting the page

    post-1266-0-84016500-1425650564_thumb.pn

    The Page is not saved and the system message shows the slash again.

    It also does not save the "Redirect To" field if I manually enter the page path.

    As you can see from the screen shot of the Redirects list, I have some that link to a page ending in .html/

    In these cases I changed the template to remove the trailing slash AFTER setting up the redirect, in the hopes it would retain that page. It does.. until I go to update it...

    post-1266-0-65191900-1425650789_thumb.pn

    Then the URL is invalidated.

    As I said, if I view the URL directly, it loads without the trailing slash in the URL, but there seems to be an issue with the system actually respecting that setting down to the core level.

    Anyone have any thoughts? Appreciate your help!

  18. I've disabled trailing slashes in the template, but across the site page references are still including a trailing slash. This is affecting Redirects and other things. The page loads correctly in the browser URL bar, but this is hindering some things from working properly.

    Has anyone run into this who knows a workaround or a fix?

    It's discussed already a bit in this thread: https://processwire.com/talk/topic/148-release-redirects/?p=88898

    ... but it's bigger than just that module so I figured I'd bring it back here.

  19. Hey kongondo, I finally fixed my comments! As usual, it was something completely innocuous: I had a base href tag in my header that was redirecting the #comments to the root URL of the site installation. Deleted that line, and suddenly my comments worked. :frantics:

    I was taking a very methodical approach to figuring this out (finally sitting down tonight after weeks of not having time to focus), thankfully my method led to the answer in five steps.

    Now that I can finally put in some example comments to play with:

    1) If I wanted to notify the admin listed in the blog_comments/Details tab, PLUS the author of the post that received a comment, what would you suggest? I don't want to add every author to the list of those who receive comments as a global setting.

    2) I have a custom admin tab that is the admin home of all authors. I'd like to identify any pending comments they should review and output a message such as "You have # comments pending review. Please visit the Comments Manager."  Would you suggest I start with the code from  "public function findComments($selector)" in MarkupBlog.module (line 541 in the latest release version)?

  20. Did you turn off the trailing slashes for those templates?

    Yes. I did just notice saving a page generates the message "Saved Page: /markets/industrial-automation.html/" even though I have triple-checked the template and there are no trailing slashes.

    Edited to Add: So is there some inherent instinct in PWire to add that trailing slash, beyond what's defined in the Settings of each page and the URL behavior of the Template?

  21. I installed ProcessRedirects from the module library into my 2.5.3 install yesterday. This morning, after getting the answer to my .html/.xml question, I tried to set up a few redirects. I'm finding that any Page whose URL ends in .html is getting / tacked onto the end after Page selection, and then the URL is considered invalid and fails to save (though quietly, it seems). I've tried changing the individual pages' URLs after I select the page and save the redirect, but when I go back I get an error message.

    In this thread, this appears to have been corrected long ago. My ProcessRedirects config page shows it's versions 1.0.0, and declares it is up to date. I see other versions in this thread, though.

    So..

    1 - Shouldn't my problem not be an issue even in 1.0.0, and how can I fix it?

    2 - Should I update to the latest version in this thread (looks like Dec 2014)? Is it stable for use in live sites?

    Thanks!

×
×
  • Create New...