Jump to content

elabx

Members
  • Posts

    1,479
  • Joined

  • Last visited

  • Days Won

    21

Everything posted by elabx

  1. My thought is that you could use a hook to add the html into the rendering of the Inputfield, or maybe you could add a Markup field in FormBuilder so you can place this link, right bellow the checkbox.
  2. Check this post: https://processwire.com/talk/topic/16932-adding-classes-to-repeater-items-for-custom-styling-in-admin/
  3. Hi everyone! I have a module that gets the top visited pages of a website, I have a problem that when the cache invalidates by time guest users doesn't seem to be able to use the module that actually get's the info. Heres the code on the template file: $mostPopular = $cache->get("mostpopular"); if(!$mostPopular){ $latest = $modules->get("GoogleAnalyticsAPI"); $latest = $latest->getMostPopular(); $pa = new PageArray(); foreach($latest as $popular){ $thePage = $pages->get($sanitizer->pagePathName($popular['path'])); if($thePage->id){ $pa->add($thePage); } } $pa = $pa->filter("template=articulo"); $mostPopular = $pa; $cache->save("mostpopular", $pa, 604800); } Here's the code for the Google Analytics module: <?php /** * GoogleAnalyticsAPI (0.0.1) * Google Analytics API Wrapper * * @author elabx * * ProcessWire 3.x * Copyright (C) 2011 by Ryan Cramer * Licensed under GNU/GPL v2, see LICENSE.TXT * * http://www.processwire.com * http://www.ryancramer.com * */ class GoogleAnalyticsAPI extends WireData implements Module,ConfigurableModule { public static function getModuleInfo() { return array( 'title' => 'Google Analytics API Wrapper', 'version' => 1, 'author' => 'Eduardo San Miguel', 'summary' => 'Description of what this module does and who made it.', 'href' => 'http://www.domain.com/info/about/this/module/', 'autoload' => true, // set to true if module should auto-load at boot 'requires' => array( 'PHP>=5.4.1', 'ProcessWire>=3.x' ), ); } public $configData = array(); public $analytics = null; public function init() { // $this->addStyle("custom.css"); // $this->addScript("custom.js"); // $this->addHookAfter("class::function", $this, "yourFunction"); } public function initClient(){ // Use the developers console and download your service account // credentials in JSON format. Place them in this directory or // change the key file location if necessary. $configData = wire('modules')->getModuleConfigData($this); $KEY_FILE_LOCATION = wire("config")->paths->assets . 'service.json'; $this->log->save("google-debug", $KEY_FILE_LOCATION); // Create and configure a new client object. $client = new Google_Client(); $client->setApplicationName("ProcessWire CMS Analytics Reporting"); $client->setAuthConfig($KEY_FILE_LOCATION); $client->setScopes(['https://www.googleapis.com/auth/analytics.readonly']); $analytics = new Google_Service_AnalyticsReporting($client); $this->analytics = $analytics; //return $analytics; } public function getMostPopular(){ $this->initClient(); $analytics = $this->analytics; $VIEW_ID = "123456789"; // Get unique pageviews and average time on page. // Create the DateRange object. $dateRange = new Google_Service_AnalyticsReporting_DateRange(); $dateRange->setStartDate("7daysAgo"); $dateRange->setEndDate("today"); // Create the Metrics object. $sessions = new Google_Service_AnalyticsReporting_Metric(); $sessions->setExpression("ga:sessions"); $sessions->setAlias("sessions"); $dimensions = new Google_Service_AnalyticsReporting_Dimension(); //$dimensions->setExpression("ga:sessions"); $dimensions->setName("ga:pagePath"); $orderby = new Google_Service_AnalyticsReporting_OrderBy(); //$orderby->setOrderType("HISTOGRAM_BUCKET"); $orderby->setFieldName("ga:sessions"); $orderby->setSortOrder("DESCENDING"); // Create the ReportRequest object. $request = new Google_Service_AnalyticsReporting_ReportRequest(); $request->setViewId($VIEW_ID); $request->setDateRanges($dateRange); $request->setMetrics(array($sessions)); $request->setDimensions(array($dimensions)); $request->setOrderBys(array($orderby)); $body = new Google_Service_AnalyticsReporting_GetReportsRequest(); $body->setReportRequests( array( $request) ); $response = $analytics->reports->batchGet( $body ); foreach($response->getReports() as $i => $report){ //d($reports->getData()->getRows()); //d($reports); //$report = $reports[0]; $header = $report->getColumnHeader(); $dimensionHeaders = $header->getDimensions(); //d($dimensionHeaders); $metricHeaders = $header->getMetricHeader()->getMetricHeaderEntries(); $rows = $report->getData()->getRows(); $sessionsPerPageData = array(); for ( $rowIndex = 0; $rowIndex < count($rows); $rowIndex++) { $row = $rows[ $rowIndex ]; $dimensions = $row->getDimensions(); $metrics = $row->getMetrics(); for ($i = 0; $i < count($dimensionHeaders) && $i < count($dimensions); $i++) { $sessionsPerPageData[$rowIndex]["path"] = $dimensions[$i]; //print_r($dimensionHeaders[$i] . ": " . $dimensions[$i] . "\n"); } for ($j = 0; $j < count($metrics); $j++) { $values = $metrics[$j]->getValues(); for ($k = 0; $k < count($values); $k++) { $entry = $metricHeaders[$k]; $sessionsPerPageData[$rowIndex]["sessions"] = $values[$k]; //print_r($entry->getName() . ": " . $values[$k] . "\n"); } } } $this->log->save("google-debug", print_r($sessionsPerPageData, true)); return $sessionsPerPageData; } } } Could anyone give me a hint on why guest users wouldn't be able to use this module? If I login as admin it all works fine again, every time the cache invalidates, the info gets retrieved again.
  4. I've done it getting the actual Inputfield module, not the Fieldtype, I'd be very curious to see if the getInputfield method works! Get back to us on what works @bernhard :D
  5. I guess that's because users are pages under admin, so If a user with "guest" role (which is the default for every request made to the site) runs that code, it won't normally have access to that data, unles specified with check_access selector.
  6. I have done several integrations and I just basically grab this library through composer and use a private app credentials, the library also handles the API throttling which is extra nice when working with large amounts of data.
  7. THIS has happened to me multiple times calling it in the wrong place.
  8. Shouldn't output formatting be turned off in the $copy page, which is the one getting saved?
  9. Try: $datetofind=strtotime($date); foreach($page->special_days->find("date_value={$datetofind}, time_from!='', time_to!=''") as $special_day) { $slot_txt.=$special_day->time_from." to ".$special_day->time_to."<br/>"; }
  10. i also stumbled on this issue! Needed a drink too! Even asked a few days ago why this behaves like this! https://processwire.com/talk/topic/14638-no-input-data-when-post-form-with-ajax/?tab=comments#comment-163444
  11. Can confirm it works on PW3 too, I had some issues with the included AWS SDK: So just for trying something out because I couldn't figure out anything from the error, I switched to installing the Amazon SDK through composer to get the latest version of the SDK and I basically just had to change how the S3 client is initialized. $this->client = new S3Client([ 'version' => 'latest', //Hardcoded value, think this has to do with the SDK version? 'region' => 'us-east-2', //Hard coded value for now, could be a config field 'credentials' => [ 'key' => $this->s3_key, 'secret' => $this->s3_secret, ], ]); Also removed the require_once for the included SDK.
  12. Doesn't the previous output the link already for download?? You can use an if statement to check if there is an uploaded file: <?php if($publication->repeater_download):?> <p><?=$publication->repeater_description?></p> <a href="<?=$publication->repeater_download->url?>">Download</a> <?php endif ?> It uses naming convention, the following code will render the file content in site/template/fields/Repeater_publication.php : (EDIT: Edited some code on previous post, I was mixing Repeater Matrix field rendering with normal Repeaters) <?php //Render the repeater field in the current page $page->render("Repeater_publication"); And inside site/template/fields/Repeater_publication.php : <?php foreach($value as $publication):?> <p> <?=$publication->publication_year?></p> <?php endforeach?> Maybe you can save this for later if you already got the rendering almost done with a more common approach
  13. Try setting the output formatting for the $flexibleContentRepeater repeater matrix item (which is a page!) $flexibleContentRepeater->of(false); I also think you shouldn't be saving the page inside the hook:
  14. I think you might have a mistake here: $publications = $subpage->publication_year(); If I understand your setup correctly that returns a year integer, so looping on that will have no relevant effect. I think the final code could look like this: <?php foreach($page->children() as $subpage): ?> <!-- $subpage are the "year" pages --> <h1>Publications on: <?php $subpage->title </h2> <!-- eg. Publications on 1997 --> <?php foreach($subpage->Repeater_publications as $publication): ?> <p><?=$publication->repeater_description?></p> <a href="<?=$publication->repeater_download->url?>">Download</a> <?php endforeach; ?> <?php endforeach; There is a way to render the repeater field as its own template (or any field for what matters) with a feature called field rendering, you would have to create a template file as: templates/fields/Repeater_publication.php that actually renders some markup when calling the render method on the repeater field reference. <?php foreach($page->children() as $subpage): ?> <!-- $subpage are the "year" pages --> <h1>Publications on: <?php $subpage->title </h2> <!-- eg. Publications on 1997 --> <?php echo $page->render("Repeater_publications"); ?> <?php endforeach; And inside site/template/fields/Repeater_publication.php : <?php foreach($value as $publication):?> <p> <?=$publication->publication_year?></p> <?php endforeach?> Check this blog post for more info on field rendering, to see which variables are available in the template file: https://processwire.com/blog/posts/more-repeaters-repeater-matrix-and-new-field-rendering/#processwire-3.0.5-introduces-field-rendering-with-template-files
  15. Haven't tested but from what I read from the core files, is that InputfieldAutocomplete uses ProcessPageSearch to look for the pages matching the fields options. You could hook into the executeFor() method on ProcessPageSearch and replace the returned output with another list rendering of your own mix of pages, the ones found by the module, and the ones you define as curated at the beginning of the rendered list. I'd even bet you could add some CSS classes to make them look different.
  16. Check this documentation page, you can also add properties: https://processwire.com/api/hooks/#add_new_method
  17. Could you double check the selector is ok?? I threw in some invented field names in the selector. (sorry to omit that) It seems to me that the $submitted is not throwing a truthsy value (maybe try $submitted->count() so it returns a number which evals to true except for 0 pages found) and it's trying to create a page with the same page name. (John Smith, will crate page john-smith), also for setting the page rather use the $sanitizer->pageName(). Also, reviewing the code, maybe it's more correct to do this: if(isset( $_POST['submit'])){ //Rather only get the first page $submitted = $pages->get("parent=/entries/, (submitter_name={$input->post->name}),(mail={$input->post->mail})"); //Checks for page id, if not it's NullPage object if($submitted->id){ //Code from before }else { $session->redirect("?alert=existing-submission"); } }else { $session->redirect("?alert=form-failure"); } Hope i didn't make this more confusing haha
  18. Here the url should be add-new-recordal, so it gets read by the process module: $wire->addHookAfter("ProcessPageLister::execute", function($event) { if(wire('page')->id === 1413) { // the particular Lister instance page id $out = $event->return; $out .= ''; $btn = wire('modules')->get("InputfieldButton"); $btn->attr('data-href', "./add-new-recordal/"); $btn->addClass("pw-modal"); if(!$this->config->ajax) $out .= $btn->render(); $event->return = $out; } } I have done this in init.php but my wild guess is it should work on ready.php too: $wire->addHook("ProcessPageLister::executeAddNewRecordal", function($event) { // // Create new page and redirect to its edit section $p = new Page(); $p->template = '02_template'; $p->parent_id = 1040; $p->name = 'recordal_' . $pageRecordalsMicrotime; $p->title = 'Recordal_' . $pageRecordalsMicrotime; $p->created_users_id = $this->user->id; $p->of(false); $p->save(); $this->session->redirect(wire('config')->urls->admin."page/edit/?id={$p->id}&modal=1"); } From what I can see, the creation of the page and redirect is already performed in an iframe modal, so it will all happen in the iframe opened with the button you are rendering. Or maybe I'm missing a point here
  19. if(isset( $_POST['submit'])){ $submitted = $pages->find("parent=/entries/, (submitter_name={$input->post->name}),(mail={$input->post->mail})"); if($submitted){ $u = new Page(); $u->template = "entries"; $u->parent = $pages->get("/entries/"); $u->name = $sanitizer->text($post_name); $u->title = $sanitizer->text($upper_name); $u->save(); $u->setOutputFormatting(false); $session->redirect("?alert=form-success"); }else { $session->redirect("?alert=existing-submission"); } }else { $session->redirect("?alert=form-failure"); } This check is first_name OR mail exists already (and checks for exact value! maybe for name you want: name%=$input->post->name).
  20. What about serving the data in an endpoint? Like, not actually write it to a file but have a json response in an endpoint and asynchronously request for that and have your scripts just respond to that.
  21. Maybe it's a permission issue in the repeater matrix template used by the repeater matrix field?? Though makes me wonder why it works on Text type because that one uses the same template as the other types.
  22. You can check for AJAX calls with: $config->ajax Sets to true if request is async.
  23. Yes!! It all worked perfectly, thanks!! Thought it was taken for granted lol sorry, this is the working code: $wire->addHookBefore("TemplateFile::render", function($event){ $templateFile = $event->object; if($templateFile->page->template == "repeater_content"){ $customFileName = $this->config->paths->templates . "fields/content/{$templateFile->page->type}.custom.php"; if(is_readable($customFileName)){ $templateFile->setFilename($customFileName); $event->return = $templateFile; } } elseif($templateFile->page->template == "home" || $templateFile->page->template == "basic-content" ){ $customFileName = $this->config->paths->templates . "{$templateFile->page->template}.custom.php"; if(is_readable($customFileName)){ $templateFile->setFilename($customFileName); $event->return = $templateFile; } } }); I have some hardcoded if statements because I don't want to be checking for EVERY template, but this works nice for repeater matrix (which uses TemplateFile to render the matrix types) and any other template. Also my first snippet was misleading because I didn't want to do a user check, so I removed that too.
  24. Maybe that page also has a contact-form template assigned? If you do a $pages->get() it will only return the first page matching your selector , so if you have multiple pages with template "contact-form", it might not return the one you think of, but the first one PW encounters.
  25. Why don't you have a text field in the category page you just created? After created, you can click the title (if using ASM Select for example) to open the page and add more content.
×
×
  • Create New...