Jump to content

MarkE

Members
  • Posts

    931
  • Joined

  • Last visited

  • Days Won

    10

Everything posted by MarkE

  1. Sorry - I forgot to say that I had tried various other things, including your suggestion. I've now done those things again (with $mailOwner rather than $mail - I'd forgotten that was predefined) and recorded the error in each case. These are reproduced below as a pair of lines - code followed by error: $mailOwner = $config->admin_site->wire('mail'); Could not get the right WireMail-Module (WireMailSmtp); found: WireMailTools [My debugging line] $mailOwner = $config->admin_site->mail->new(); require_once(./WireMailSmtpAdaptor.php): failed to open stream: No such file or directory in M:\laragon\www\BawdHall\site\assets\cache\FileCompiler\site\modules\WireMailSmtp\WireMailSmtp.module on line 290 The second of these seems to be calling the right module (WireMailSmtp) but can't find the file because $config is always for instance_A. This seems similar to the issue we had with Runtime Markup.
  2. Yes. The php for that field is Availability.php, which is in instance_B, and calls mail as described above. Not sure what more info you want re "where and how". Abbreviated code for this script is below: <?php namespace ProcessWire; $headers = getallheaders(); $permittedNonPW = array_map('trim', array_map('strip_tags', explode(',', $page->bodyTop))); $permittedPW = array_map('trim', array_map('strip_tags', explode(',', $page->bodyFoot))); // If site is a PW site, then need to deal with the different instances if (in_array($headers['Host'], $permittedPW)) { $site = $config->admin_site; $config->sitePages = $config->admin_site->pages; } else { $site = wire(); $config->sitePages = $pages; } ///////////////////////////////////////////////////////// // Process any form results: /////////////////////////////////////////////////////////// // define variables and set to empty values $name = $email_address = $phone = $fromToDate = $adults = $children = $pets = $provbooking = $message = $spambot = ""; $fromerror = $toerror = $radioerror = $propertyName = ""; function test_input($data) { //......... return $data; } if (isset($_GET["submit"])) { $out = ''; if ($_SERVER["REQUEST_METHOD"] == "POST") { $propertyName = test_input($_POST["property"]); //...... //fill variables } //...... $mail = wireMail(); if($mail->className != 'WireMailSmtp') { wire()->log->save('debug', 'Could not get the right WireMail-Module (WireMailSmtp); found: ' . $mail->className); } else { $mail->to($to) ->from($myemail) ->subject($email_subject) ->bodyHTML($email_body_top . $email_body); $numsent = $mail->send(); if ($numsent > 0) { //..... $out .= '<script>alert("Your request has been submitted - you should receive an automated email acknowledgement shortly.")</script>'; //..... $url = strtok($_SERVER['REQUEST_URI'], '?'); $out .= '<script>window.location.assign("' . $url . '");</script>'; return $out; } /////////////////////////////////////////////// /////////////// MAIN PAGE //////////////////// ////////////////////////////////////////////// $currentPath = $files->currentPath(); $out = ... // Fills the availability table ... ////////////////////Don't forget the form itself////////////////////////////// if (in_array($headers['Host'], $permittedPW)){ wire()->log->save('debug', 'Calling booking form sitePages = ' . $config->sitePages->get('/')->title . ', $headers["Host"] is ' . $headers["Host"]); $out .= $config->admin_site->files->render($currentPath . 'booking_form.php'); } else { $out .= wire()->files->render($config->paths->templates . 'RuntimeMarkup/booking_form.php'); } //////////////////FINALLY RETURN THE OUTPUT!!!/////////////////////////// return $out; This works fine for $permittedNonPW but not for $permittedPW.
  3. In your terminology, lets say instance_B is "site" and instance_A is "site-web". Both sites sit under the same root, sharing the same wire/ (i.e. a multi-site installation). in _init.php (part of the template rendering) in instance_A: $config->admin_site = new ProcessWire($config->paths->root . 'site/'); I use $config->admin_site so that it can be accessed anywhere (assuming the current context is instance_A). Ah, that's a bit (!) more complicated. Instance_A accesses a runtime markup field in instance_B thus: $adminPage = $config->admin_site->pages->get("template=Availability, name=bawd-hall-availability"); $availabilityTable = $adminPage->runtime_markup_availability; This field renders php in the file Availability.php, which lives in instance_B ("site") Availability.php renders a form thus: $out .= $config->admin_site->files->render($currentPath . 'booking_form.php'); where $currentPath is $files->currentPath(); - i.e. booking_form is a sibling of Availability. (BTW, Availability.php checks the host name in the headers to determine whether it is being called as a second instance or not). booking_form's action is $_SERVER['REQUEST_URI'] (i.e. the original page, thus running Availability.php again). Availability.php tests (isset($_GET["submit"]) ) and if true processes the POST variables from the form. After validation, the mail is constructed from these variables with $mail = wireMail(); etc. For more background (if you really want ? ) you can see here, where @kongondo was extremely helpful getting the RuntimeMarkup Fields module working in a multi-instance environment.
  4. I've used this module a number of times and it works well. Now I am trying to use it in a multi-instance environment and am a bit stuck. Is this possible at all? To explain: I have two sites (in a PW multi-site setup - although I think the issue would be the same even if they were completely separate). "site" is a private admin site and "site-web" is a public website. "site-web" accesses "site" via an instance as described in https://processwire.com/blog/posts/multi-instance-pw3/. "site" has a contact form which is accessed by "site-web" and has WireMailSmtp installed. When completed, an email is sent using $mail=wireMail(). This works fine when the public site is not a PW site. However, when it is a PW site (as "site-web" is), the context for WireMail is "site-web", not "site", so $mail returns a WireMail class, not a WireMailSmtp class. I cannot find a way to call WireMail in the right instance context. If I try and call WireMailSmtp directly, it is operating in the wrong context and fails. I guess I could install a copy of WireMailSmtp on "site-web", but then I need to maintain the config on both sites. Besides it seems counter-intuitive that using a non-PW site for the public site should be easier than doing it in PW! I'd be grateful for any ideas or insights.
  5. Nor me. It seems like PT calls the RM PHP file more than once. The first time it works properly with a Pageimage, but then later calls submit a string/integer/boolean. The code to bypass the latter has the side effect that the RM field now has nothing in it - hence the need for the reload. All pretty messy! I've tried various debugging routes, but can't work out how the multiple calls are happening.
  6. This seems to fix it: https://github.com/furf/jquery-ui-touch-punch
  7. Here's my complete work-round for the problem with runtime markup images in a Page Table field. Something that prevents the problem occurring in the first instance would be better though! 1. Add the following condition for images rendered in the runtime markup: if (is_a($image, '\ProcessWire\Pageimage')) $out .= '<img src="' . $image->url . '"/>'; 2. Add the following to admin.js (the 2 functions are lifted from InputfieldPageTable.js): /*******************************************************************************************************************/ /* Work-round to reload and re-enable sorting of Page Table field, which includes runtime markup, after modal edit */ /*******************************************************************************************************************/ $(document).on('pw-modal-closed', function(event) { var wrap = $(this).find('.InputfieldPageTable'); if ($(wrap).attr('id')) $('#' + wrap.attr('id')).load(document.URL + ' #' + wrap.attr('id') + '> *'); // To just load the inner html of wrap - avoiding duplicating it }); $('.InputfieldPageTable').mouseenter(function () { if (!$('tbody').hasClass("ui-sortable")) { var $table = $('tbody').closest('table'); InputfieldPageTableSortable($table); } }); function InputfieldPageTableUpdate($table) { var value = ''; if(!$table.is('tbody')) $table = $table.find('tbody'); $table.find('tr').each(function() { var pageID = $(this).attr('data-id'); if(value.length > 0) value += '|'; value += pageID; }); var $container = $table.parents('.InputfieldPageTableContainer'); var $input = $container.siblings('.InputfieldPageTableSort'); $input.val(value); } function InputfieldPageTableSortable($table) { $table.find('tbody').sortable({ axis: 'y', start: function(event, ui) { var widths = []; var n = 0; $table.find('thead').find('th').each(function() { widths[n] = $(this).width(); n++; }); n = 0; ui.helper.find('td').each(function() { $(this).attr('width', widths[n]); n++; }); }, stop: function(event, ui) { InputfieldPageTableUpdate($(this)); } }); } /*******************************************************************************************************************/
  8. Putting this: $(document).on('pw-modal-closed', function(event) { var wrap = $(this).find('.InputfieldPageTable'); if ($(wrap).attr('id')) $('#' + wrap.attr('id')).load(document.URL + ' #' + wrap.attr('id')); }); in the admin js avoids the need to hack the InputfieldPageTable.js. Again, there may be side effects that I haven't noticed. One side-effect I have noticed is that, after closing the modal, the rows in the Page Table can no longer be sorted by dragging - a full window refresh is still required for that.
  9. To make this work inside a page table, I had to hack the InputfieldPageTable.js as follows: function InputfieldPageTableDialog() { var $a = $(this); var url = $a.attr('data-url'); var title = $a.attr('data-title'); var closeOnSave = true; var $container = $(this).parents('.InputfieldPageTableContainer'); var wrap = $(this).closest('.InputfieldPageTable'); // MDE added var dialogPageID = 0; var noclose = parseInt($container.attr('data-noclose')); var modalSettings = { close: function(event, ui) { if(dialogPageID > 0) { var ajaxURL = $container.attr('data-url') + '&InputfieldPageTableAdd=' + dialogPageID; var sort = $container.siblings(".InputfieldPageTableSort").val(); if(typeof sort != "undefined" && sort.length) ajaxURL += '&InputfieldPageTableSort=' + sort.replace(/\|/g, ','); $.get(ajaxURL, function(data) { $container.html(data); $container.find(".Inputfield").trigger('reloaded', ['InputfieldPageTable']); $container.effect('highlight', 500, function() { var $table = $container.find('table'); $table.find('tbody').css('overflow', 'visible'); InputfieldPageTableSortable($table); // restore appearnace of any items marked for deletion var deleteIDs = $container.siblings("input.InputfieldPageTableDelete").eq(0).val().split('|'); if(deleteIDs.length) { for(var n = 0; n < deleteIDs.length; n++) { var deleteID = deleteIDs[n]; $table.find("tr[data-id=" + deleteID + "]") .addClass('InputfieldPageTableDelete ui-state-error-text ui-state-disabled'); } } }); }); if ($(wrap).attr('id')) $('#' + wrap.attr('id')).load(document.URL + ' #' + wrap.attr('id')); // MDE added } } } .... The new lines are the ones annotated "MDE added" I haven't found any unwanted side-effects (so far ..) but obviously I'm a bit unhappy about amending core code unless it warrants a PR, so I would be grateful for any thoughts on this, or other ideas.
  10. Great module, but I'm having a couple of minor issues (unrelated, I think). The first issue seems intermittent and I can't work out why : In some cases, I can't get the inclusion of .js and .css to work. I've triple-checked all the naming etc. but the files just don't seem to load. My work-round (easy enough) is just to load the files in the php. The second issue may be because I am stretching the fieldtype's capability! I am using it within a PageTable field as follows. The PageTable field ("panelled_carousel") has a template "Panelled_carousel" which has fields "title", "imagePages" (a page reference field linking to a page with template "Image" and an image field "image_single") and "runtime_markup_images" (a runtime markup field with php file "RuntimeMarkup/Images.php"). The php file is (including a bit of debugging): $imagePages = $page->imagePages; bd($page, 'page with carousel'); $out = ''; wire()->log->save('debug', 'Page is ' . $page->title); foreach ($imagePages as $imagePage) { bd($imagePage, 'imagePage'); foreach ($imagePage->image_single as $image) { bd($image, 'image'); if (is_a($image, '\ProcessWire\Pageimage')) $out .= '<img src="' . $image->pia("width=200")->url . '"/>'; } } return $out; The RM field is updated when the imagePages field changes by javascript/AJAX : When editing the Page Table field, this all works well - any changes in the imagePages (add/re-order/delete etc) are immediately reflected in the RM field. However, when saving the Page Table Field and returning to the host page, the RM PHP throws an error unless I catch it with the condition - is_a($image, '\ProcessWire\Pageimage') - in the code above. The reason is that in some cases $image seems to be taking a string, integer or boolean value, even though $imagePage has class Page and the dump shows it is the right page. Trapping this error means that the images in the table are all blank after the save. However refreshing the page puts everything right again. So not a deal-breaker but a bit odd. To illustrate, here is the top page with the page table (including images): Clicking on "Blue" to edit an item we get: Then, clicking save and returning to the top page, the images do not render: The debugging shows that this is not because Images.php has not run, but because $image is of the wrong type (as described above). Refreshing the page restores the images. Any ideas? EDIT: I should add that the problem does not seem to be related to my .js script, or even RuntimeMarkup specifically as exactly the same issue happens in a Page Table with @Robin S's RuntimeOnly module with no js attached to it. So it seems to be something to do with how the runtime markup is interacting with the page table display.
  11. That's because it was caused by a bit of rogue code on my part!! Cleaned it up now - sorry for the diversion. I'm actually having some (unrelated?) issues with the RM module at the moment. I'll investigate further and post on the module thread if there is a real problem.
  12. Sorry, the answer to that is a bit complicated. I am not using the RM module to refer to the css file. It is linked in the PHP script. This detects whether the host site (site 2) is on a permitted list stored in the availability page in site 1 which contains the RM field. There are two such lists - one for non-PW sites and one for PW sites. The script grants the permissions required for it to access the templates/fields it needs and also passes the css as an in-line style. So I just had to make sure that the path was correct for the css (and js) like this: } elseif (in_array($headers['Host'], $permittedPW)) { $currentPath = $files->currentPath(); $calendarUser = $config->admin_site->users->get("name=calendar"); // calendar has role that only allows access to the availability page $config->admin_site->users->setCurrentUser($calendarUser); $cssText = file_get_contents($currentPath . 'styles/Availability.less.css'); if ($cssText) { $out .= '<style>' . $cssText . '</style>'; } $js = file_get_contents($currentPath . 'scripts/Availability.js'); if ($js) { $out .= '<script>' . $js . '</script>'; } } else { Maybe a bit hacky - but works ? It makes no difference - I get the error from site 1 if the RM module is not in site 2, or from site 2 if it is in both.
  13. I fixed the css and it all works. I'm getting PHP notice from Tracy: PHP Notice: Object of class ProcessWire\DefaultPage could not be converted to int in ...\FieldtypeRuntimeMarkup.module:536 That line is $root = $mode == 2... in public function getDefaultPath($defaultPath, $mode=1) { $config = $this->wire('config'); $root = $mode == 2 ? $config->urls : $config->paths; if(2 === (int) $defaultPath) $defaultPath = $root->siteModules;// /site/modules/ else $defaultPath = $root->templates;// /site/templates/ return $defaultPath; } Doing a bd(), it would seem that $mode is the host page for the RM field, not an integer! Not causing a problem in my case, since $root = $config->paths is OK, but odd. I wasn't getting this error with the previous version (or my hacked copy).
  14. Many thanks for that @kongondo. Any reason for that? I need it on both sites (a really useful module ? ). A quick test seems to indicate that it works OK if installed on one or both sites, but I will investigate more. As you say, my css isn't working properly after this but hopefully I can fix that. I'll spend some time with it and let you know of any issues. Thanks again!
  15. Here's what I have: public function getDefaultPath($defaultPath, $page, $mode=1) { bd($page, 'page'); $config = $this->wire('config'); if ($mode == 2) { $rootUrl = preg_replace('/assets.*/m','',$page->filesUrl()); $config->setUrl('templates_RM', $rootUrl . 'templates/'); $config->setUrl('siteModules_RM', $rootUrl . 'modules/'); $root = $config->urls; } else { $rootPath = preg_replace('/assets.*/m', '', $page->filesPath()); $config->setPath('templates_RM', $rootPath . 'templates/'); $config->setPath('siteModules_RM', $rootPath . 'modules/'); $root = $config->paths; } if(2 === (int) $defaultPath) $defaultPath = $root->siteModules_RM;// /site/modules/ else $defaultPath = $root->templates_RM;// /site/templates/ return $defaultPath; }
  16. No. I can't use $site->config->paths->site inside your module, just $config->paths->site. But if I hooked it there would be more flexibility. Sorry, I missed that. I did originally add the domain parameter, but I got an "overloaded" error message, so I removed it. Here's the code: $config->admin_site = new ProcessWire($config->paths->root . 'site/'); Using $config means it's available everywhere in site 2 (which is actually called site-web).
  17. You would need to add $page as a parameter to make it usable in the way I describe. That always returns site 2, so no use. It needs to be something that takes $page as its reference point.
  18. As I mentioned earlier, this: $rootPath = preg_replace('/assets.*/m','',$page->filesPath()); $config->setPath('templates', $rootPath . '/templates/'); works. as $page is in the site-1 context.
  19. Me too! But to clarify. The code I suggest will set the template path to that which hosts the page with the RM field (site 1 - the app - in this case, but should make no difference in a single-instance case). By the originating site, I meant site 2 - the public site.
  20. A suggestion: In FieldTypeRuntimeMarkup.module, getDefaultPath method, set an additional parameter $page (and update references), then use the following: $rootPath = preg_replace('/assets.*/m','',$page->filesPath()); $config->setPath('templates', $rootPath . '/templates/'); (and similarly for /modules/ and $config->urls) This will set the paths for templates etc. relative to the site which hosts $page, rather than the originating site. There may be a better way of getting the root path without having to do the preg_replace, but I can't see one at the moment. EDIT: Then you need to use $defaultPath = $config->paths->templates; etc. I'll try and work this up more fully, but for my code to work properly, I also need to make my PHP for the RM field "multi-instance aware".
  21. That might be possible, if that were to be the only method. However, methods 1 and 2 require the data to be processed in the admin app as the front-end for those methods is not PW (and both these methods work well). In any case, I have been experimenting a bit with your suggestion, by putting my RM code on site 2 (since that is where the module is looking for it) and have been running into problems with selectors not working properly - will continue to investigate this. Excerpts of code are given below. The page is rendered using the markup regions strategy. _init.php is loaded first, the template is in Prices.php and the rendering is via _main.php. In _init.php $admin = new ProcessWire($config->paths->root . 'site/'); In _main.php <div id="wrapper"> <!-- content replaced by template --> </div> In Prices.php <div id="wrapper"> ....... <div id="availability"> <?php $adminPage = $admin->pages->get("template=Availability, name=bawd-hall-availability"); $availabilityTable = $adminPage->runtime_markup_availability; bd($adminPage, 'admin page'); bd($adminPage->availabilityColumns, 'admin page columns'); bd($availabilityTable, 'admin page runtime'); ?> <?= $adminPage->title ?> <?= $adminPage->runtime_markup_test ?> <?= $availabilityTable ?> </div> ---- </div> The bardumps illustrate that the other fields appear OK (as do $adminPage->title and $adminPage->runtime_markup_test {your test field - only works with the PHP placed in site-2/templates}). $availabilityTable (the original RM field) does not work even after placing a copy of the php in site-2/templates and modifying the $pages-> to invoke the site-1 instance, owing to the selector issue mentioned above, which I am investigating. EDIT: The selector issue is my code, I think. I got the field to render eventually in site 2 (minus a lot of css) with replicating all the PHP for the field in site-2/templates and modifying $pages etc. to pick up the right instances. Part of the issue seemed to be the need to explicitly set the $user in site 1, otherwise the field could not pick up the required data. I was assuming that since the API was all in PW that superuser in site-2 would allow API access in site-1; it doesn't! So, if we can get the RM module to pick up the code from the correct place, it may all work nicely.
  22. Yes. To explain further: Site 1 is a web app which handles the bookings. Site 2 is the public website for the property. I need to publish the availability from 1 to 2. The result is the availability table you see at https://www.bawdhall.co.uk/prices. The admin app will handle multiple properties, each with their own availability page. The availability page in the admin app hosts the RM field. It is intended that the publishing of availability could take place in one of 3 ways: iframe in the public site (which could be anywhere). The availability template in the admin app provides the rendering for this (using the RM field). access the admin app PW API from a non-PW site on the same server (this is the method used for the link given above and works very well using the RM field on the admin site). access the admin app PW API from another PW instance (what I am now trying to do). The code for the RM field is really rather big and accesses a lot of data from across the admin site (site 1), not just the (non RM) fields on the availability page. As well as the table you see, it also hosts a booking form. You will realise from the above that this code needs to sit within the admin site to handle cases 1 and 2 - I really don’t want to replicate it in a slightly different form for case 3 to access all the underlying data directly and re-build the table. Besides, it seems nonsensical that case 2 should work “out of the box” but not case 3. I don’t know if I have made things harder by putting both sites in a multi-site setting. Maybe it would help if they were completely separate sites, whilst still on the same server. However, I read Ryan’s comment that it would be good to use the same PW version so I though that multi-site was a sure way to achieve that. I’ll answer the last point on code in a later post.
  23. OK. Results as follows: Undefined function Filename does not exist (it is looking on site 2, not site 1 - where the page and field are) render() on null call to undefined function wire() I tried them all with and without RM module in site 2. The results are exactly the same (if the site 2 module is present it will run that, otherwise it will run the site 1 module). If I put the file in site-2/templates then alternative (2) works (with and without the module in site 2). (But it makes no sense to have the file in a different site from the page and field).
×
×
  • Create New...