Jump to content

horst

PW-Moderators
  • Posts

    4,077
  • Joined

  • Last visited

  • Days Won

    87

Everything posted by horst

  1. Example for a use case with importing things. This is a raw draft with a bit pseudo code: // you have created a queue in PW, the ID of the page is 2000 for example // here is some skeleton code for an importer that uses this queue // get and validate the queue handle if(! ($queue = $pages->get('id=2000')->wireQueue())) exit(); // we could not get the Queue page // now start to scan / read data for your imports, wrap each record into an array and put it into the queue foreach($pages->find(YOURSELECTOR) as $p) { $data = array($p->field1, $p->field2); $queue->addItem($data); } // now start to process your items by pulling one after the other from the Queue while($timer < $maxtime) { $data = $queue->getItem(); // process the $data ... } $session->redirect('./');
  2. A task is something that needs to be done, e.g. sending an email at the end of someones buying in a shop. Sending the email is the "task". You can use this module for what ever you like. It is really very basic. If you has setup one Queue, you can access it (like in the code snippet in the first post) from a template file or from within a bootstrapscript. You need to know the name or id of the page that holds the Queue, thats all you need. Than you can pass data records to it. With the textfile storage every data record should be an array. I don't know if this can be useful for your import script. Definitely a Pro would be if you are limited with script execution time by the server. Then you can scan / read in all needed pages / images and put them into the queue without starting to process them. After you have finished this read in, you start processing them by pulling out items from the queue as long as you are within the time limit. If you reach critical time, you stop processing and end the script. It needs to be reloaded somehow, e.g. could be done without any cron but via session->redirect() as last command that ends the script. This way you strat with a fresh amount of execution time. No record gets lost as it could be if you use only session for storage. Maybe, you know the name Stack? It something similar as a Queue. Difference is, in a Queue is something like a pipe with both sides open. What is put in first, gets pulled out first at the other end: FiFo (First in First out). A stack is something where you put one item upon the other, maybe also a pipe, but with one end closed. Therefore you can only pull the last item from it, not the first: FiLo (First in Last out) WireQueue module is nothing more than the basic implementation of it into PW. ?? Ok ?? If you are unsure if this can be useful for your >cron task<, maybe you can explain a bit how this is be done. From where and when do you get the items that needs to be imported and how do you process the images and what is the next step, etc.
  3. Hey mr. Ivan! Nice to hear from you. There can be some different usecases. Normally you want to use a Queue for decoupling time intensive tasks from the websites responses so that the users doesn't have to wait long times. For example, if someone booked / collected something on a site, there will finally an email sent to him / her. If the script would wait until it could connect to the smtp server and has sent the email, it could be that the smtp server is busy and delays the sending. With a Queue, you simply drop in this job and give fast response to the users screen: "Thanks for your booking! We will response by email soon.". Another script will pickup the job and proceed it. So, decoupling time intensive tasks and optionally split up the work to multiple workers if usefull / necessary. Another example would be sending a newsletter to 5k recipients. It seems better to me to have those temporary data seperated from the main Database in regard of Backups / Restores. With WireQueue you can create and controll Queues visually in the backend. This wouldn't be necessary but I found it usefull and comfortable. Currently there is only a very simple StorageModule available with plaintext files. The next one uses SQlite Databasefiles what is much more comfortable as it opens the WireQueue to not only put and get jobs into it but also can be used to store the current state of each job. Or if the collected data should be exported to other systems for further processing, etc. You can use whatever storage type you like. You only needs to create your own storage module upon the abstract class that comes with the module. Currently there are only comments in the code itself and the WireQueueTextfile module for detecting how it should be done. But it isn't complicated. You can setup one that uses a MYSQL table in another DB than that from your PW installation. etc. etc. More and better information will come later in next step. Does that help?
  4. @ukyo: this looks very well. I have bookmarked this post because I allready use lazysizes and respimg in two projects, but I think I haven't it that well organized as you have. Next possibilty I have time for it, I will compare mine with yours and update / reorganize mine where needed. Many thanks for sharing!
  5. I'm really not sure if this works every time. Lately I have tricked my self with using dashes - - - in fieldnames and not underscores _ _ _ . Fieldcreation was via API, where the fieldname was stored in a class constant: const MYFIELDNAME = 'my-new-fieldname'. The new fieldname of the created field worked out as: 'my_new_fieldname'. Later in the code, where I want access one field with a selector like $page->get("name=" . CLASS::MYFIELDNAME), it doesn't work. I'm not sure if this was with fields of type text / integer or only Page, but I perfectly remember that it hasn't worked. ---- There was also this: https://processwire.com/talk/topic/8709-croppableimage/page-2#entry86866 (read this and the two following posts)
  6. Hm, is 'Slider1' a valid fieldname? I thought fieldnames are only lowercase?
  7. Not with Likes but with Follows you can use the IPboard filter: ------------------ Another approach: Something like Kongondo uses, (Browserbookmarks with SearchCapabilities), but browser independent, could be: to use the bowsers functionality to send pagelinks by email. (It opens your default email program with a new email where the subject and body part is populated with the page title and page url). Before sending, you can add as many notices, text / tags / keywords / categories, or some copy / pasted segments from the webpage, etc. When sending this to a dedicated emailaddress that gets parsed by a module within PW, you have a browser independent storage with fulltext search.
  8. I forgott to mention that it shows usefull information directly in the pagetree: total number of pending items and current states of the queues via icons
  9. ------------------------------------------------------------------------------ This is officially released now with some fixes and a second storage handler based on SQLite3. ------------------------------------------------------------------------------ WireQueue WireQueue is a module that allows easy creation and usage of Queues in ProcessWire. It is based upon a basic (parent) module that can or should have one or multiple StorageHandler modules. This alpha pre release contains a basic plain text storage module, WireQueueTextfile. The base module creates the needed: FIELDS (wire_queue_type, wire_queue_state, wire_queue_storage_options) TEMPLATES (wire-queue-container, wire-queue-storage, wire-queue-tools) PAGES (wire-queues = container for all Queuepages, wire-queue-storages = container for StoragetypePages) ROLE (wire-queue-admin) Each storage module creates one page under wire-queue-storages. New Queues can be created in the backend by adding a new page under "Wire Queues". After creation one have to select a Storage type from availables list and publish the page. After that, there are some buttons available to start / pause / and close the queue. Putting and getting data to and from the queue is done via API calls. First you have to get the page that holds the queue object. // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->WireQueue()) { // wrap your data into an array and pass it into the queue $success = $queue->addItem($data); ... } // get and validate the queue handle if($queue = $pages->get(SELECTOR_TO_DESIRED_PAGE)->WireQueue()) { $data = $queue->getItem(); ... } Thats basically all what you want from a queue. Following are a few conveniences: $queue->getPage()->title gives you the title of the queue, ($queue->getPage() returns the page object) $queue->className() shows the StorageType of the queue $queue->getState() and $queue->getStateStr() returns the current state of a queue: 1 = new / empty 2 = enabled / running 3 = paused 4 = closed / archived $queue->itemCount() gives the total number of all pending items in the queue Here is code that gives an overview of all Queues in the system: $container = $pages->get('template=wire-queue-container'); $bodyContent = "<h1>$container->title</h1>"; $bodyContent .= "<p>There are currently {$container->numChildren} Queues defined:</p>"; $bodyContent .= "<ul>"; foreach($container->children() as $p) { if(! ($queue = $p->wireQueue())) continue; $bodyContent .= "<li>{$queue->getPage()->title}<ul>"; if(!$queue->ready2use()) { $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>This Storagetype is not ready to use! The System seems not to provide all requirements.</li>"; $bodyContent .= "</ul></li>"; continue; } $bodyContent .= "<li>{$queue->className}</li>"; $bodyContent .= "<li>{$queue->getStateStr()} ({$queue->getState()})</li>"; $bodyContent .= "<li>Currently are {$queue->itemCount()} items pending!</li>"; $bodyContent .= "</ul></li>"; } $bodyContent .= "</ul>"; Following are a screenshots of the backend The module is on Github: https://github.com/horst-n/WireQueue Would be nice if someone has time and can test it a bit and report back.
  10. No, its not a bug. CroppableImages's UI was made before the crop functionality was introduced. CroppableImages was planned to add more functionality and better space usage to the UI, therefore it was not build on top of the core images UI. Thus truncate the path to all further updates / changes to the core image. It would be really cool if someone of the guys who are building the new images UI also could (re)build the croppableimages UI back to use the default one only with the additional buttons for the crop, after the core UI image is finished.
  11. Good find! ..., and welcome to the forums. PS: do you know PIA? She can assist in images API coding. $url2 = $image->size(100, 100, array('upscale' => false, 'cropping' => false, 'suffix' => array('noupscsale', 'nocrop')))->url; can be written like $url2 = $image->contain("size=100, suffix=noupscsale-nocrop")->url;
  12. Looks good, only thing I would check is: You probaply will give a name and / or title to your new page. I would suggest to create it first and check if a page with that given name or title already exists: $parent = wire('pages')->get('/site-manager/bookings/'); $genericTitle = $somehowCreatedFromYourDataOrTimestampOrWhatever; $p = $pages->get("title={$genericTitle}, template=booking, parent.id=" . $parent->id); if(0 == $p->id) { // page does not exist, we can create a new one $p = new Page(); // create new page object $p->template = 'booking'; // set template $p->parent = $parent; $p->title = $genericTitle; ...... } else { // UUUPs! A Page with that title exists. // This case must be handled different! ...... }
  13. look here: https://processwire.com/talk/topic/11842-change-timezone-per-user-in-admin/#entry110099
  14. I have had this too and it is also reported on Github. The error comes from other third party admin modules that try to fetch the id of the currently edited page in admin. The error is raised because those third party modules blindly assume the id is an integer value and passes it unsanitized, for example, via $pages->get($input->get->id). That will raise those errors. Very hard to debug and detect is such a unsanitized selector request when it is called in a autoloaded modules ready event! I have submitted a patch / pull request for that issue on github. PS: Devs of third party modules that need to fetch the currently edited page can do it at least like: $p = $pages->get('id=' . $input->get->id); // but better validate the id before using: if(!is_int($input->get->id) && !is_numeric($input->get->id)) return false; // or only using is_int() ?? if(is_int($input->get->id)) { $p = $pages->get('id=' . $input->get->id); . PPS: I have to admit that I had done it wrong too in some of my custom modules.
  15. You can use if / elseif / else, but you also can use switch(). foreach($pageArray as $child) { switch($child->template) { case: 'home': // your code here break; case: 'anothername': // your code here break; default: // your code here if there is a default for this, otherwise yiou can ommit it } // ... }
  16. horst

    404 Hits

    I have some more different in my collection
  17. Repeaters (can) create pages before you need them. This is for convenience. The default value is set to 3. You also can setup a repeater field to only create pages on demand. If I remember right, this would need one additional save click for every repeater item you add in the edit process. 1) check delete trash 2) set the repeater fields to NOT create temp pages, the default is set to 3 (!) 3) look under Admin -> Pages -> ... for a hidden folder with the repeater children and delete them
  18. Thanks Raymond. Have updated it in the code example above.
  19. I found wireTempDir myself a few days ago, so memory fingerprint was fresh.
  20. $tmpDir = new WireTempDir('someName'); // add files $fileBasename = 'basename.ext'; $filename = $tmpDir->get() . $fileBasename; file_put_contents($filename, base64_decode($b64Data)); $page->files->add($filename); // repeat for all files ... // optionally, at the end call $tmpDir->removeAll(); EDIT: Ah, you already know / found WireTempdir() EDIT2: If one use WireTempDir for very timeconsuming tasks, one optionally can define a maxAge for it, different than the default 120 seconds: $tmpDir = new WireTempDir('someName', array('maxAge' => 300));
  21. Yes, best way would be only to dynamically change all date reading, but not to alter date writing.
  22. The meaning is, that, if there isn't explicitly set a value, the return would be NULL (blank field) and not the integer 0.
  23. I'm not very familiar with (user) timezones. A quick search through PWs wire files shows that timezone is used in ProcessWire::config with ini_set('date.timezone', $config->timezone); So I would change $config->timezone and PHPs date.timezone. But haven't worked / tested with that! In regard of getting the original / default value and not a runtime-changed value from $config, there is this possible workaround: function getDefaultValuefromConfig($key) { $config = new stdClass(); include( wire-config.php ); include( site-config.php ); // now we have merged default settings of $config in local scope of this function // and can return the requested one return $config->$key; }
  24. Because it depends on login / logout, my first thought is: $this->pages->addHookAfter('Session::logout', $this, 'yourFunction'); $this->pages->addHookAfter('Session::login', $this, 'yourFunction'); If this doesn't fit well, there is also $this->pages->addHookBefore('ProcessLogin::execute', $this, 'yourFunction'); $this->pages->addHookBefore('ProcessLogin::executeLogout', $this, 'yourFunction'); // or $this->pages->addHookAfter('ProcessLogin::execute', $this, 'yourFunction'); $this->pages->addHookAfter('ProcessLogin::executeLogout', $this, 'yourFunction');
  25. What's about not yet saved content in other fields when reloading? Will this get saved first? Also, is it good to save (optionally massive) changes without the knowing of the user? At least, I think it only could be an option, not the default.
×
×
  • Create New...