PHP and Concrete 5 count subpages - php

Making mobile site with Concrete5 and using page list block with custom template. I'm trying to count sub pages using PHP.
<?php foreach ($pages as $page):
// Prepare data for each page being listed...
$title = $th->entities($page->getCollectionName());
$url = $nh->getLinkToCollection($page);
$target = ($page->getCollectionPointerExternalLink() != '' && $page->openCollectionPointerExternalLinkInNewWindow()) ? '_blank' : $page->getAttribute('nav_target');
$target = empty($target) ? '_self' : $target;
$description = $page->getCollectionDescription();
$description = $controller->truncateSummaries ? $th->shorten($description, $controller->truncateChars) : $description;
$description = $th->entities($description);
$mies = 0;
?>
<li class="ui-btn ui-btn-icon-right ui-li-has-arrow ui-li ui-btn-up-c" data-theme="c"><div aria-hidden="true" class="ui-btn-inner ui-li"><div class="ui-btn-text"><a target="<?php echo $target ?>" class="ui-link-inherit" href="<?php echo $url ?>">
<h2 class="ui-li-heading"><?php echo $title ?></h2>
<p class="ui-li-desc"><?php echo $description ?></p>
</a>
</div><span class="ui-icon ui-icon-arrow-r ui-icon-shadow"></span><span class="ul-li-count ui-btn-corner-all ul-count-second"><?php echo count($mies) ?></span></div></li>
<?php endforeach; ?>
So, probably need to use Count function(or length?), I don't know. If I am editing wrong place please advice if you have any experience in Concrete5 cms.

If you want to show the corresponding page number in the span element in your code:
<span class="ul-li-count ui-btn-corner-all ul-count-second"><?php echo $mies; ?></span>
If you want to show the remaining sub-pages, then in the html code snippet above just replace $mies with count($pages) - $mies like:
<span class="ul-li-count ui-btn-corner-all ul-count-second"><?php echo count($pages) -$mies; ?></span>
You would first have to initialise $mies before you start the forloop so it should be something of the form:
<?php
$mies = 0;
foreach ($pages as $page):
//Rest of your code and increment $mies with every iteration
$mies ++; //This ensures that you are counting the corresponding pages
?>
If you want to get the count of total number of sub-pages, you just have to echo out $mies outside the for block may be like:
<?php
endforeach;
echo $mies; //Shows you the total number of pages processed inside the for loop.
//or Just find the length of pages array
echo count($pages);
?>
As far as getting the length of array is concerned you could use count or sizeof. I stumbled upon a SO question about using count or sizeof method for finding the length of an array.
This should get you started in the right direction.

You need the parent ID;
$parentId = Page::getCollectionParentId();
Note that Page::getCollectionParentId() gets the current page's parent ID,so you may want to try;
$parentId = $page->getCollectionParentID();
Then create a new PageList to filter with and filter by the parentId;
Loader::model('page_list');
$pl = new PageList();
$pl->filter(false, '(p1.cParentID IN ' . $parentId . ')');
// Get the total
var_dump($pl->getTotal());
This is untested but the theory makes sense.

This is likely a bit simpler.
$pl->getTotal()
$pl is the PageList object that is set in the controller.
Also, these days you can just use the h() method instead of writing out $th->entities()
Edit: I should clarify that you don't need to do a $pl = new PageList() because $pl is already set to the PageList object in the controller and passed to the view.

Related

Display whole fields from group (file + ACF)

I made the ACF plugin group with files to download. In group I have fields "File 1", "File 2"...etc.
I would like to display all attached files to page. It is possible to display all fields belong to group? I try with basic code, but in this case I have only 1 file.
How can I add iteration to this or display all fields?
<?php
$file = get_field('attachment_1');
if( $file ):
// vars
$url = $file['url'];
$title = $file['title'];
$caption = $file['caption'];
if( $caption ): ?>
<div class="wp-caption">
<?php endif; ?>
<ul>
<li><a href="<?php echo $url; ?>" title="<?php echo $title; ?>">
<span><?php echo $title; ?></span>
</a>
</li>
<ul>
<?php if( $caption ): ?>
<p class="wp-caption-text"><?php echo $caption; ?></p>
</div>
<?php endif; ?>
<?php endif; ?>
As all your fields are set up individually, it isn't just a matter of looping through an array of all your fields of the same type (i.e. just your file fields).
There are a few ways that might work for you:
Option 1.
If all the field names for your files follow the same naming pattern and are named sequentially, you could loop using the name.
Example, assuming your fields are named attachment_1 up to attachment_5:
$statement = get_field('name_of_your_statement_field');
//do whatever you need to with $statement
for ($i=1; $i<=5; $i++){
//use the number from the loop to find the file by name
$file = get_field('attachment_'.$i);
if( $file ){
// display file details as appropriate
}
}
Option 2.
If the file field names do not follow the same pattern, you could loop through an array of the field names.
Example:
$statement = get_field('name_of_your_statement_field');
//do whatever you need to with $statement
// Create an array with the field names of all your files
// N.B. This also lets you specify the order to process them
$file_fieldnames = array('file_1', 'file2', 'another_file');
foreach ($file_fieldnames as $fieldname) {
$file = get_field($fieldname);
if( $file ){
// display file details as appropriate
}
}
Option 3. If you want to loop through ALL fields on the post/page, you can save the fields into an array.
This might seem like the most generic approach at first, but it is complicated by the fact that you don't know what type each field is in order to know how to process and display them... you first have to work out what field type it is. You could do this by name (similar to above) or you could try to identify what each field by checking the field content.
Note, checking the field content is very risky, as there are other field types that can have similar featured (e.g. a file is not the only type that can have a url) so I wouldn't advise that strategy unless you are 100% sure you'll never change the field group or add another field group to the post/page.
Example:
$fields = get_fields();
foreach ($fields as $fieldname => $content) {
if (is_string ($content)){
// display the string
}
else if (is_array($content) && $content['url']) {
// then you could assume its a file and display as appropriate
}
}
Note that none of this code is tested. However it should give you an idea of the logic behind each option so you can decide what works for you.
UPDATE based on new code provided:
See below based on the code in your JSFiddle. I've ignored the caption outside the file list because it makes no sense - every file can have its own caption.
<?php
for ($i=1; $i<=5; $i++){
//use the number from the loop to find the file by name
$file = get_field('attachment_'.$i);
if( $file ){
$url = $file['url'];
$title = $file['title'];
$caption = $file['caption'];
// now display this file INSIDE the loop so that each one gets displayed:
?>
<li>
<a href="<?php echo $url; ?>" title="<?php echo $title; ?>" target="_blank">
<span><?php echo $title; ?></span>
</a>
<?php if( $caption ): ?>
<p class="wp-caption-text"><?php echo $caption; ?></p>
<?php endif; ?>
</li>
<?php
} // end if
} // end for loop
?>
<ul>
If you understand arrays, I'd suggest you add the file details into an array and then do a second loop to display the files... however I'm guessing you're not that proficient with basic coding constructs as you don't understand loops, so I've tried to keep it simple. I strongly recommend that you do some tutorials on programming basics if you are attempting to write code.

How to set condition in following code for marking current page in pagination?

I am trying to set a condition for php- mysql pagination so that it can change the current page "li" to "li class="active" " to mark the current selected page. I am new to php and searching for such pagination tutorial but no luck.
I have done so far what is working but not able to mark selected page. Here $id is for detecting the current page id. How can I set if condition ( or other) so that I can mark the current page item in the pagination? Thousands thanks for helping me.
<ul class="pagination">
<?php if($id > 1) {?> <li>Previous</li><?php }?>
<?php
for($i=1;$i <= $page;$i++){
?>
<?php
if ($id>1)
{ ?>
<li class="active"><?php echo $i;?></li>
<?php }
?>
<!-- <li><?php echo $i;?></li> -->
<?php
}
?>
<?php if($id!=$page)
//3!=4
{?>
<li>Next</li>
<?php }?>
</ul>
You could change your for loop from
<?php
for($i=1;$i <= $page;$i++){
?>
<?php
if ($id>1)
{ ?>
<li class="active"><?php echo $i;?></li>
<?php }
?>
<!-- <li><?php echo $i;?></li> -->
<?php
}
?>
to:
<?php
for($i=1;$i <= $page;$i++){
$class=($i==$id)? ' class="active"' : '';
echo '<li'.$class.'>'.$i.'</li>';
}
?>
If I've understood your code properly, $page represents total pages and $id represents the current page, this will set the current page number as the active class and leave the other pages without the class
Assuming that $id is the current page number, and that $page is the total number of pages, you need to highlight only one by doing the following in your loop:
if($i==$id) // highlight
else // don’t highlight
Your main errors are that you didn’t test whether $i==$id, and you didn’t have an alternative unhighlighted version.
I really think that you should simplify your code by separating your logic from the HTML. It becomes very unreadable otherwise, and very hard to manage.
I have taken the liberty of doing just that. This way you can see where the logic does the hard work, an you only need to print the results in the HTML.
<?php
$id=3; // test value
$page=20; // test value
$li=array(); // temporary array for convenience
$template='<li%s>%s</li>';
if($id>1) $li[]=sprintf($template,'',$id-1,'Previous');
for($i=1;$i<=$page;$i++) {
if($i==$id) $li[]=sprintf($template,' class="active"',$i,$i); // Current
else $li[]=sprintf($template,'',$i,$i);
}
if($id<$page) $li[]=sprintf($template,'',$id+1,'Next');
$li=implode('',$li); // convert to string for printing
?>
<ul class="pagination">
<?php print $li; ?>
</ul>
You will also see two techniques to make things easier:
I use an array as a temporary container. It is easier to add items this way and then to implode it into a string afterwards
sprintf makes it easier to define a template string, so you can manage the HTML component more easily, and fill in the gaps when the time comes.

How to create simple pagination in PHP page

Below is my Code.
<?php
$folder_name=$_GET['folder_name'];
$dirname = "customized_kits/images/";
$images = glob($dirname."*");
$filecount = count( $images );
$i=0;
for($i=0;$i<200;$i++) { ?>
<div class="col-md-2"> <div class="photos">
<div id="images1">
<a href=# data-lightbox="roadtrip">
<?php
if($filecount>$i) {
$filename = substr($images[$i], strrpos($images[$i], '/') + 1);
echo '<img src="'.$images[$i].'" style="width:150px;height:150px" /><br/>';
?>
<i class="fa fa-remove"></i>
<?php } else {
echo '<a ><img style="width:150px;height:150px;background-color:#eee" /></a>';
} ?>
</div>
</div>
</div>
<?php } ?>
Here I created 200 boxes with foreach loop I want to show 20 divs for single page and with help of pagination I want to show other divs.I searched in many websites I didnt get exact answer please help me to get out of this issue.
Okay so from your code you can have 200 values of $i and you want to paginate them in segments of 20. Let us start off by adding a script above your code to get the range that needs to be displayed. Page number comes as a GET parameter in number. ex example.com/feeds?number=2.
<?php
$pageno = $_GET['number']; // Page number from frontend
// Now this value will give you 1,2,3 etc
$start = $pageno*20;
// $start contains the initial offset or the value of `$i` from to start
for($i=$start;$i<$start+20;$i++) {
// Will only show 20 elements on the page
}
?>
Remember this is a very basic example. Although i would recommend using range in sql query instead so you don't have to load the complete dataset in each query.
More explanation
Suppose you have M results and you want to show N results on each page, the results on page x would start from x*N to x*(N+1) pure math here. In your code you are iterating $i over the whole loop rather just iterate over that specific range to get results. The value of x is the example is the page number that we get from number in GET verb.

For each loop in PHP to display certain item from database

So I'm wanting to make a way to display the 2nd newest row from my database. So my example (To help better explain it) If i have 10 rows. I want to display only the second newest one. Not the newest one but the one right after it. Or the maybe even the third one. I have my working code below and i see the for each loop. But I'm not sure how to only display the one I'm wanting it to display. I also don't think how i have it set up is the most efficient way of acomplishing this.
I am using concrete5 for this site and the main idea is for composer so i can post a new post and the pull a recent news feed but showing the second post.
Here is my current code: (This shows the first post)
<?php
defined('C5_EXECUTE') or die("Access Denied.");
?>
<div id="blog-index">
<?php
$isFirst = true; //So first item in list can have a different css class (e.g. no top border)
$excerptBlocks = ($controller->truncateSummaries ? 1 : null); //1 is the number of blocks to include in the excerpt
$truncateChars = ($controller->truncateSummaries ? $controller->truncateChars : 255);
$imgHelper = Loader::Helper('image');
foreach ($cArray as $cobj):
$title = $cobj->getCollectionName();
$date = $cobj->getCollectionDatePublic(DATE_APP_GENERIC_MDY_FULL);
$author = $cobj->getVersionObject()->getVersionAuthorUserName();
$link = $nh->getLinkToCollection($cobj);
$firstClass = $isFirst ? 'first-entry' : '';
$entryController = Loader::controller($cobj);
if(method_exists($entryController,'getCommentCountString')) {
$comments = $entryController->getCommentCountString('%s '.t('Comment'), '%s '.t('Comments'));
}
$isFirst = false;
?>
<div class="entry">
<div class="title">
<h3>
<?php echo $title; ?>
</h3>
<h6 class="post-date">
<?php
echo t('Posted by %s on %s',$author,$date);
?>
</h6>
</div>
<div class="excerpt">
<?php
$a = new Area('Main');
$a->disableControls();
if($truncateChars) {
$th = Loader::helper('text');
ob_start();
$a->display($cobj);
$excerpt = ob_get_clean();
echo $th->entities($th->shorten($excerpt,$truncateChars));
} else {
$a->display($cobj);
}
?>
</div>
<div class="ccm-spacer"></div>
<br />
<div class="meta">
<?php echo $comments; ?> <?php echo t('Read the full post'); ?> <i class="icon-chevron-right"></i>
</div>
</div>
<hr class="blog-entry-divider"/>
<?php endforeach; ?>
</div>
To build upon what the others have written as comments:
What you've pasted is a concrete5 view. You'll notice there's no db querying or PageList building in there. For that, you need to look in the controller. (This looks like a page list block view, so the controller will be in / concrete / core / controllers / blocks / page_list.php (on c5.6+).
The concrete5 api code to do what the others have suggested (let mysql handle the skipping) is done within the ->get() call. So, on about line 135:
$pl->get(1, 1);
Remember not to modify the files directly, but to override them the c5 way. There are plenty of tutorials on this on the c5 website.

How to use PHP to apply a CSS class based on an inconsistent pattern of image tiles?

I am displaying posts one week at a time and each of the respective days for that particular week will contain thumbnail images for each individual post. The goal of the feed will look something like the screenshot diagram below (the brackets indicate a post with it's respective post count.)
As you can see I produce an uneven number of posts on a daily basis. There's no way of me knowing how many post I'll publish. I would like to be able to apply a CSS class (in the code snippet below you'll see I call the CSS class "margin") and this will be used in my CSS so I can apply margin to all center images.
Each row in the diagram has AT MOST 3 images across (i.e. 3 columns: left, middle, right); however it can have an unlimited number of rows down. I would like to be able to apply this "margin" class to all posts in the middle column.
I began to code up how this gets accomplished but what I can't figure out is how to apply the class only to all middle posts. A friend told me to use modulus, but can't figure how to implement it properly. Let me know if you need any further clarification.
Please see this screenshot of diagram I made to help depict what I am looking to achieve. I think this will help you understand the question better:
<section class="post-by-date">
<?php
$day_check = '';
$today = get_the_date();
$year = date('Y');
$week = date('W');
$news_query = new WP_Query('category_name=main&year=' . $year . '&w=' . $week);
while ($news_query->have_posts()) : $news_query->the_post();
$day = get_the_date('j');
if ($day != $day_check) {
echo "<h3>" . get_the_date() . "</h3>";
}
$post_count = $news_query->current_post;
$found_posts = $news_query->found_posts;
if ($post_count % 3 == 0) {
$apply_css_margin = TRUE;
}
else {
$apply_css_margin = FALSE;
}
?>
<article id="post-<?php the_ID(); ?>" <?php if($apply_css_margin) { post_class('margin'); } else { post_class(); } ?>>
<a href="<?php the_permalink(); ?>">
<?php the_post_thumbnail('featured'); ?>
</a>
</article>
<?php $day_check = $day; endwhile; ?>
</section>

Categories