This code for extract files dir and title. The user download when clicked the file link. I need to count then number of downloads. How to do this with cakephp or php?
downloads_controller.php:
function index() {
$this->set('downloads', $this->paginate());
}
downloads/index.ctp:
<?php
$title = $download['Download']['title'];
// output filetitle
$filename = '/files/'.$download['Download']['filename'];
// output http://localhost/tet/files/un5titled0.rar
echo $this->Html->link($title, $filename,array('escape' => false));
?>
not this way i am afraid.
you either need to redirect from an action (which counts before redirecting) or use Media view to pass it through.
thats how I do it.
In the action you can then raise the count prior to sending the file.
If you want to count downloads, you should create a function that serves those downloads and create a field in your database that increments downloads each time this function is called.. For example
Call the following function from your view passing the $filename and the $id
To try out at first use, taking ID=4 as one of the downloads ID in your DB
http://www.yourdomain.com/downloads/download/4
And Then your controller would be...
Class DownloadsController extends AppController{
// All your other functions here
function download($id = null){
$this->Article->updateAll(
array('Download.count' => 'Download.count+1'),
array('Download.id' => $id)
);
$download = $this->Download->findById($id);
$this->set('filename', $download['Download']['filename']);
//$filename is an array that can then be used in your view to pass the file for download. to find out what is has you can use debug($filename) in your view
}
}
Then you need to create a special layout so the browser knows that the request file is a download and you will also need to create a view for download.ctp. Basically when you click the file link on your page, it will call this function which will use its view to serve the file.
You can access the following which will provide some insight on what needs to be done..
TUTORIAL LINK
There are lots of techniques, though in the simplest way, you can use a text file to do this.
Create a txt file and write 0 (zero) into it.
In your index function, read the content of your file.
$counter = file_read_contents('counter.txt');
Increase the read value by 1.
$counter++;
Write new value into file again.
file_put_contents('counter.txt', $counter);
So, it counts downloads and keep number in that file.
function download($id = null) {
$download = $this->Download->findById($id);
$this->set(compact('download'));
if(!empty($id)) {
// increment the number of items downloads
$this->Download->save(array(
'Download' => array(
'id' => $id,
'counts' => ($download['Download']['counts'] + 1)
)
));
}
header('Location: http://localhost/tet/files/'.$download['Download']['filename']);
exit();
}
Related
I'm trying to generate an excel file using PHPExcel Module in the action_info function with the following code :
function mymodule_export_data_action(&$object, $context = array()) {
if (isset($object->uid)) {
$uid = $object->uid;
}
elseif (isset($context['uid'])) {
$uid = $context['uid'];
}
if ($uid) {
module_load_include('inc', 'phpexcel');
$filename = 'mymodule--download-' . uniqid() . '.xls';
$filepath = variable_get('file_public_path', conf_path() . '/files') . '/' . $filename;
$result = phpexcel_export(
array('Nom', 'Prenom', 'Date de naissance', 'Adresse email'),
array(
array('A1', 'B1'),
array('A2', 'B2'),
), $filepath);
if ($result === PHPEXCEL_SUCCESS) {
drupal_set_message(l('Click to download', $filepath));
}
else {
}
}
}
This is working pretty fine when having just one node, but when there's more than one it generates a new file for each one, which also good but my purpose is to have one file for all nodes. It has been days and I really hope for someone to put me in the right direction.
Thank you in advance
Here is the solution by using views module, views_data_export module, 2 lines of PHP code and some lines of jQuery.
Just follow these steps:
1st Install views and views_data_export modules
2nd (a) Create views page and data export, this video
will help you to export the data according to the
filter(s)
2nd (b) Don't forget to add nid field in the views page that will use to get NIDs
2nd (c) Now, create one more views data export (that again starts here, if you need) and create exporting PATH different than the first data export (created on step 2nd (a)) but keep remember you don't have to update Attach to option under the DATA EXPORT SETTINGS section, it should looks like this Attach to: none.
2nd (d) Now, add nid as contextual filter in the views and choose Provide default value = Content ID from URL like this and check the checkbox Allow multiple values like this
3rd Add two lines of PHP code somewhere in the template.php OR top of the tpl of views page if you have already created (by the way I did it with the tpl named as views-view--export-multiple-rows--page.tpl.php).
if($_SERVER['REQUEST_METHOD'] == 'POST') {
drupal_goto("export_selected/".implode(',', $_POST['export']));
}
4th Add below jQuery code in the JS file that will be render on this page like custom.js and **change classes **
jQuery(function($){
jQuery('.feed-icon a:first-child').text('Export All');
jQuery('td.views-field-nid').each(function() { //class of NID added in step 2nd (b)
var t = jQuery(this);
var id = jQuery.trim(t.text());
t.html('<input type="checkbox" name="export[]" value="" />');
t.find('input').val(id);
});
//Below .view-export-multiple-rows class is of views class (main views page)
$('.view-export-multiple-rows').wrap('<form method="POST" class="export-form"></form>');
$('.export-form .view-content').append('<input type="submit" value="Export Selected" name="submit" />');
});
If you follow all these steps properly, I believe you have done with:
To export all rows
To export filtered rows
To export specific rows
I hope this will help you or at least give you an idea.
Thanks
currently the adminEmail is set in the params.php file. I am trying to change the 'adminEmail' dynamically and then I can assign the email value I want. There is the code in the params.php.
return array(
// this is displayed in the header section
'title' => 'title here',
// this is admin email
'adminEmail' => 'admin#email.com',
But the admin emails can be more than one(eg. admin1#email.com, admin2#email.com), how can I set admin email dynamically in params.php ?
Thanks in advance!
You can try set multiple emails on adminEmail, and at runtime access it using index. E.G
//asign multiple email ids to adminEmail as array
'params'=>array(
// this is used in contact page
'adminEmail'=>array('webmaster#example.com','sany#gmail.com','xxx#yahoo.com','webmaster2#example.com')
),
//access it using array index at runtime as your requirement
<?php echo Yii::app()->params['adminEmail'][1];?> //sany#gmail.com
<?php echo Yii::app()->params['adminEmail'][2];?> // xxx#yahoo.com
OR
Create a static method on a class that will generate dynamic email ids and
then set it to your adminEmail param .e.g
class Email
{
public static function generateEmailIds()
{
//or any other way to generate email ids or id
return array('webmaster#example.com',
'sany#gmail.com',
'xxx#yahoo.com');
}
}
'params'=>array(
// this is used in contact page
'adminEmail'=>Email::generateEmailIds(),
)
Well, although I don't recommend this approach, what you want to do can be done like this:
You need to store your array in a file in serialized form (that is, call function serialize() on it. That will turn the array into a string.
You can read the file and unserialize it (that is, call function unserialize() on it. That will turn the string that you read form file back into a PHP array.)
$handle = fopen('path/to/file','rb');
$contents = fread($handle,999).
$array = unserialize($contents);
set 'adminEmail' to what you want it to be:
$array['adminEmail'] = 'new#email.com;
or even
$array['adminEmail']= array(..lots of emails..);
then you need to turn the array into a string and write the array back to file. Like this, for example:
$serialized_contents = serialize($array);
fwrite($handle, $serialized_contents);
There may be more efficient ways to do this if you want to.
hi i've got a gallery page. this gallery page has a gallery image object with an has_many relation.
private static $has_many = array(
'GalleryImages' => 'GalleryObject'
);
my gallery object has an image upload field. I want to set the upload folder to the title of the gallery page
i tried this with no result
$visual->setFolderName('Galerie/'.$this->Gallery()->Title);
and this (what i would prefer)
public function getGalleryTitle() {
$galleryTitle = $this->Gallery()->Title->First();
$uploadFolder = str_replace(' ', '-', $this->$galleryTitle);
return $uploadFolder;
}
$visual->setFolderName('Galerie/'.$this->$uploadFolder);
the second returns and error (undefined variable uploadFolder ?!) and my upload folder is now set to "Galerie/DataList"
can someone tell me how to convert the output of $uploadFolder so that i get back the title?
EDIT:
GalleryHolder: http://www.sspaste.com/paste/show/5267dea3579a6
GalleryPage: http://www.sspaste.com/paste/show/5267dee4c9752
GalleryObject: http://www.sspaste.com/paste/show/5267df0af1a65
you where almost there..
Here is your edited getGalleryTitle() function.
It is basically checking if the GalleryObject has a parent Gallery via $this->GalleryID. Since it is a has_one relation the column will be named GalleryID.
Then we get the Gallery object with $this->Gallery() and get it's title with $gallery->Title.
I've also replaced your str_replace with SilverStripe's URLSegmentFilter class. Which will removed spaces and other special characters non welcome in URL, a better solution.
public function getGalleryTitle()
{
if ( $this->GalleryID )
{
$gallery = $this->Gallery();
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
Then in the getCMSFields() function, when creating your UploadField we just call the getGalleryTitle() function that returns the string for the folder name.
$visual = new UploadField('Visual', _t('Dict.IMAGE', 'Image'));
$visual->setFolderName('Galerie/'.$this->getGalleryTitle());
A few notes..
$this references the current Object instance, so you can't use $this->$galleryTitle to access a variable you just created in your function, $galleryTitle by itself is enough.
You were calling $this->$uploadFolder in setFolderName, this doesn't work for the same reason, and also, using $uploadFolder by itself wouldn't work since this variable was created in the scope of another function. So we just call the function we defined on our Object with $this->getGalleryTitle() since it returns the value we want.
This should work fine, but keep in mind that if the Title of the Gallery changes at some point, the folder name will change too. So you might end up with images uploaded in many different folders for the same gallery... I personally wouldn't advise it, unless you implement some kind of "Title locking system" or some way to keep the "correct" or first "valid/acceptable" Gallery title in a separate object property that can't be edited and use this in the folder name.
I usually only use the ID in those case ($gallery->ID), as this will not change.
edit
Another version of getGalleryTitle() that should work even if the GalleryObject isn't saved yet.
public function getGalleryTitle()
{
$parentID = Session::get('CMSMain')['currentPage'];
if ( $parentID )
{
$gallery = Page::get()->byID( $parentID );
$filter = new URLSegmentFilter();
return $filter->filter( $gallery->Title );
}
else{
return 'default';
}
}
First, I check to see whether we're on the CMSSettingsPage or in a ModelAdmin page (Should you be using them). You want to get all the information about which class the controller is managing as it's data record. (If you have firebug, FB($this) in getCMSFields() on the related DataObject (DO) will show you the page managed under DataRecord)
Controller::curr()->currentPage() will get you the current page the DO is being managed on, and ->URLSegment will get the page url name, though you could use Title or MenuTitle also.
Here is an example which will set up a folder underneath assets/Headers to save images in. Running this on the HomePage (ie URL Segment 'home') will create and save objects into the folder /assets/Headers/home.
if (Controller::curr()->class == 'CMSSettingsController' || Controller::curr() instanceof Modeladmin) {
$uploadField->setFolderName('Headers');
}
else
{
$uploadField->setFolderName('Headers/' . Controller::curr()->currentPage()->URLSegment);
}
Does anyone know how I can get the just uploaded images ids and access the array of them from my controller?
My model: http://pastebin.com/aJW0vq22 (do_upload())
And here's the relevant part of my controller:
class Site extends CI_Controller {
function index() {
//enable profiler
//$this->output->enable_profiler(TRUE);
$data = array();
$this->load->model('Site_model');
if($this->input->post('upload')) {
$data['upload'] = $this->Site_model->do_upload();
//echo '<hr />' . $this->Site_model->total_uploads;
//set the users edit session for their image
$uploaded_image_id = $this->Site_model->get_last();
$values = array(
'image_id' => $uploaded_image_id,
'session_id' => $this->session->set_userdata('session_id')
);
$this->session->set_userdata('edit', $values);
//var_dump($values);
//show uploaded image
redirect($uploaded_image_id . '?links');
}
Currently I've just been using 'get_last()' to just get the last thing added to the database, but now I've added the ability to upload multiple things at once I doubt I can still, any ideas?
edit:
basically the end result i'm trying to get is
redirect('id1, id2, id3' . '?links');
You could save the file names of the just uploaded images into a session array and then query your database for the ids of those file names. This will reliably return the desierd ids.
I see that for your get_last you use a query that returns the last image added to the table. But what if you have 500 users uploading an image at the same time?
Is this facebook link populated fully from the DB? Or, is it a physical file with PHP in it? Just, how is this page called?
http://www.facebook.com/profile.php?id=49300915&sk=photos
They probably do something like:
if(isset($_GET['id'], $_GET['sk'])) {
mysql_query("SELECT info, photos FROM users WHERE id = '$id'");
}
I'm trying to ask, how do they include this page? Is it like Drupal / any CMS where the PHP and page is stored in the DB, or is it a physical file on the server? If the latter, what's the best way to get the file (case insensitive URL)?
I would have a class with a single method, which reads 'sk' and runs another method, depending on what it's value is.
One method would be 'photos' which would read 'id' and fetch a photo from the database. It would then run another method, displayPage, which will display a page from that data.
The displayPage method takes a "template" filename and an array of variables to provide to the template. It sets up a smarty object, provides the variables, and instructs it to display the template.
Inside the template, I'd include another template for the global header that's on every page in the site, then i'd have the html page content, using smarty to insert dynamic values, then include a global footer.
Note that i've simplified this system a lot. A real page like that would take me a week to write all the code, since a big website does a lot of stuff just to display a simple page (for example: find out if the logged in user actually has access to the page... i don't have access to the example one you gave).
<?php
// profile.php
class ProfileController
{
public function run()
{
if ($_GET['sk'] == 'photos')
return $this->photosPage();
}
protected function photosPage()
{
$id = (int)$_GET['id'];
$result = mysql_query("select * from photo where id = $id");
$photo = mysql_fetch_object($photo);
$this->displayPage('view-photo.tpl', array('photo' => $photo);
}
protected function displayPage($templateFile, $templateVariables)
{
$smarty = new Smarty();
foreach ($templateVariables as $variableName => $variableValue) {
$smarty->assign($variableName, $variableValue);
}
$smarty->display($templateFile);
}
}
$conntroller = new ProfileController();
$controller->run();
And the smarty code:
<!-- view-photo.tpl -->
{include file='head.tpl'}
<h1>View Photo {$photo->name|escape}</h1>
<img src="{$photo->src|escape}" width="{$photo->width|escape} height="{$photo->height|escape}>
{include file='foot.tpl'}